TUTORIAL 3 : Register dan Login Menggunakan Laravel

  1. Pada tutorial ini, melanjutkan dari tutorial sebelumnya
  2. Sebelum memulai, pastikan anda sudah mengaktifkan xampp terlebih dahulu
  3. Pertama – tama, kita buat tabel users menggunakan migration lewat cmd

4. Kemudian buka file create_users_table.php pada function up ( )

5. Sekarang kita proses

6. Coba anda cek di database

7. Kemudian untuk membuat fitur login dan register secara bersaman, kita cukup memerintahkan artisan untuk membuatnya

8. Sekarang coba buka di browser nya, masukkan http://localhost/LaraStore/public/

9. Buka file RegisterController.php lalu sesuaikan dengan gambar di bawah

10. Lalu klik menu REGISTER , kemudian isi data sesuai field

11. Apabila berhasil register, maka secara langsung akan di arahkan ke halaman Data Barang

12. Sekarang kita tambahkan tombol logout pada Header, buka file header.blade.php masukkan code baru dari baris 120 – 138 seperti gambar dibawah.

13. Buka file LoginController.php lalu sesuaikan dengan gambar di bawah

14. Terakhir, buka file ProductController.php, lalu tambahkan construct auth

Membuat Restful dengan Codeigniter

Pada kesempatan kali ini, kita coba membuat restful dengan framework Codeigniter. Untuk persiapan yang kita butuhkan dalam tutorial kali ini adalah sebagai berikut :

  1. Install aplikasi Xampp, yang dapat didownload pada halaman ini
  2. Framework Codeigniter
  3. Database tutorial_rumah_coding dengan table siswa yang sebelumnya telah kita gunakan pada tutorial ini
  4. Instal aplikasi postman, yang dapat didownload pada halaman ini
  5. Instal Composer, yang dapat didownload pada halaman ini

Setelah tools yang kita butuhkan berhasil dijalankan, langkah pertama adalah kita perlu menginstall library untuk Codeigniter agar dapat membuat restful api. kita dapat menemukan library ini pada github atau packagist dengan kata kunci “codeigniter rest”. Adapun cara installnya adalah sebagai berikut :

Jika instalasi sukses, maka akan muncul didalam project Codeigniter kita folder bernama ‘codeigniter-restserver’ dimana didalam folder tersebut ada beberapa file yang perlu kita copy kedalam folder tutorialrumahcoding/application/. Adapun file tersebut adalah sebagai berikut :

  1. copy file idap.php dan rest.php yang terdapat pada tutorialrumahcoding/codeigniter-restserver/application/config kedalam folder tutorialrumahcoding/application/ config
  2. copy file db_helper.php yang terdapat pada tutorialrumahcoding/codeigniter-restserver/application/helpers kedalam folder tutorialrumahcoding/application/ helpers
  3. copy file Format.php dan REST_Controller.php yang terdapat pada tutorialrumahcoding/codeigniter-restserver/application/libraries kedalam folder tutorialrumahcoding/application/ libraries

Selanjutnya Kita Coba Membuat Model dengan nama file SiswaModel.php didalam folder tutorialrumahcoding/application/ Models. Berikut baris Perintahnya :

<?php
class SiswaModel extends CI_Model{
// response jika field ada yang kosong
  public function empty_response(){
    $response['status']=502;
    $response['error']=true;
    $response['message']='Field tidak boleh kosong';
    return $response;
  }
// function untuk insert data ke tabel siswa
  public function add_person($nama,$email,$password,$telepon,$pelajaran){
if(empty($nama) || empty($email) || empty($password) || empty($telepon) || empty($pelajaran)){
      return $this-&gt;empty_response();
    }else{
      $data = array(
        "nama"=&gt;$nama,
        "email"=&gt;$email,
        "password"=&gt;$password,
        "telepon"=&gt;$telepon,
        "pelajaran"=&gt;$pelajaran

      );
$insert = $this-&gt;db-&gt;insert("siswa", $data);
if($insert){
        $response['status']=200;
        $response['error']=false;
        $response['message']='Data siswaditambahkan.';
        return $response;
      }else{
        $response['status']=502;
        $response['error']=true;
        $response['message']='Data siswagagal ditambahkan.';
        return $response;
      }
    }
}
// mengambil semua data siswa
  public function all_person(){
$all = $this-&gt;db-&gt;get("siswa")-&gt;result();
    $response['status']=200;
    $response['error']=false;
    $response['data']=$all;
    return $response;
}
}
?&gt;

Kemudian buat sebuah Controllers dengan nama Siswa.php didalam folder
tutorialrumahcoding/application/ controllers. Berikut baris perintahnya :

<?php
require APPPATH . 'libraries/REST_Controller.php';
class Siswa extends REST_Controller{
// construct
  public function __construct(){
    parent::__construct();
    $this-&gt;load-&gt;model('SiswaModel');
  }
// method index untuk menampilkan semua Data Siswa menggunakan method get
  public function index_get(){
    $response = $this-&gt;SiswaModel-&gt;all_person();
    $this-&gt;response($response);
  }
// untuk menambah Data Siswa menaggunakan method post
  public function add_post(){
    $response = $this-&gt;SiswaModel-&gt;add_person(
        $this-&gt;post('nama'),
        $this-&gt;post('email'),
        $this-&gt;post('password'),
        $this-&gt;post('telepon'),
        $this-&gt;post('pelajaran')
      );
    $this-&gt;response($response);
  }

}
?&gt;

Setelah Controllers dan Modelnya kita buat, saatnya kita coba memasukkan data kedalam database dengan method post dan mengambil data dengan method get menggunakan aplikasi postman. Pertama kita coba untuk memasukkan data kedalam database dengan cara berikut :

Saat memasukkan data dengan method POST, maka hasilnya akan terlihat seperti ini :

Kemudian coba mengambil data menggunakan method GET seperti ini :

Maka hasilnya akan terlihat seperti ini :

TUTORIAL 2 : CRUD menggunakan Laravel

  1. Pertama-tama aktifkan xampp anda terlebih dahulu, ikuti langkah tutorial sebelumnya .
  2. Buka salah satu Web Browser Anda Google Chrome, Mozilla, dll. Lalu ketik http://localhost/dashboard/ pada link URL anda.

3. Jika sudah muncul tampilan seperti gambar di atas, klik phpMyAdmin.

4. Klik New.

5. Isikan nama tabel dengan lara_store . Lalu klik Create.

6. Kemudian buka file .env   di dalam folder LaraStore untuk pengaturan database, isi sesuai gambar di bawah

7. Sekarang, kita atur menu pada sidebar. Buka file sidebar.blade.php hapus baris code yg di block seperti gambar dibawah

8. Ubah baris code pada sidebar.blade.php  seperti gambar dibawah

9. Sekarang coba buka di browser nya, masukkan http://localhost/LaraStore/public/admin

10. Buatlah sebuah tabel dengan migration, menggunakan php artisan lewat cmd

11. Kemudian buka folder database/migrations/ cari file dengan akhiran create_products_table.php, masukkan code seperti gambar di bawah

12. Lalu hapus dua file paling atas dalam folder
database/migrations/

13. Gunakan perintah berikut untuk membuat tabel pada database

apabila muncul keterangan seperti ini, maka tabel berhasil dibuat

14. Sekarang kita buat model dari Product, masukkan perintah berikut

15. Buatlah sebuah folder dengan nama product

16. Install library tambahan untuk membuat form lebih mudah, masukkan perintah berikut

17. Sekarang kita atur dalam config/app.php tambahkan code berikut

code diatas berada dalam ‘providers’ =>

code diatas berada dalam ‘aliases’ =>

18. Buatlah sebuah file create.blade.php dalam folder product

19. Masukkan code berikut ke dalam file create.blade.php

@extends('admin/admin')
@section('content')
    <div class="row">
        <div class="col-12">
            {{ Form::open() }}
                <div class="card">
                    <div class="card-header">
                        <h3 class="card-title">Tambah Barang</h3>
                    </div>
                    <div class="card-body">
                        @if(!empty($errors->all()))
                        <div class="alert alert-danger">
                            {{ Html::ul($errors->all())}}
                        </div>
                        @endif
                        <div class="row">
                            <div class="col-md-6">
                                <div class="form-group">
                                    {{ Form::label('name', 'Nama Barang') }}
                                    {{ Form::text('name', '', ['class'=>'form-control', 'placeholder'=>'Masukkan Nama Barang']) }}
                                </div>
                                <div class="form-group">
                                    {{ Form::label('price', 'Harga Barang') }}
                                    {{ Form::text('price', '', ['class'=>'form-control', 'placeholder'=>'Masukkan Harga Barang']) }}
                                </div>
                            </div>
                            <div class="col-md-6">
                                
                                <div class="form-group">
                                    {{ Form::label('condition', 'Kondisi Barang') }}
                                    {{ Form::select('condition', ['baru'=>'baru', 'bekas'=>'bekas'], null,
                                        ['class'=>'form-control']) }}        
                                </div>
                                <div class="form-group">
                                    {{ Form::label('image', 'Gambar Barang') }}
                                    {{ Form::file('imageFile', ['class'=>'form-control']) }}        
                                </div>
                            </div>
                        </div>
                        <div class="row">
                            <div class="col-12">
                                {{ Form::label('description', 'Description') }}
                                {{ Form::textarea('description', '', ['class'=>'form-control', 'placeholder'=>'Enter description', 'rows'=>5]) }}
                            </div>
                        </div>
                    </div>
                    <div class="card-footer">
                        <a href="{{ URL::to('admin') }}" class="btn btn-outline-info">Kembali</a>
                        {{ Form::submit('Proses', ['class' => 'btn btn-primary pull-right']) }}
                    </div>
                </div>
            <!-- </form> -->
            {{ Form::close() }}
        </div>
    </div>
@endsection

20. Sekarang kita buat Product controller , serta route Resource agar mempermudah penggunaan method.

21. Tambahkan Route::resource seperti gambar di bawah

22. Buka file ProductController.php tambahkan code dalam method create( ) seperti gambar dibawah

23. Sekarang coba buka di browser nya, masukkan http://localhost/LaraStore/public/admin/product/create


24. Tambahkan code berikut pada file create.blade.php

25. Aktifkan folder public untuk menyimpan gambar

26. Buka file ProductController.php tambahkan code seperti gambar di bawah

27. Buka file ProductController.php tambahkan code dalam method store( )

public function store(Request $request)
    {
        //
        $rules =[
            'name'=>'required',
            'price'=>'required|integer',
            'imageFile'=>'required|mimes:jpg,png,jpeg,JPG',
            'description'=>'required'
        ];

        $pesan=[
            'name.required'=>'Nama Barang Tidak Boleh Kosong',
            'price.required'=>'Harga Barang Tidak Boleh Kosong',
            'imageFile.required'=>'Gambar Tidak Boleh Kosong',
            'description.required'=>'Deskripsi Tidak Boleh Kosong'
        ];

        $validator=Validator::make(Input::all(),$rules,$pesan);

        //jika data ada yang kosong
        if ($validator->fails()) {

            //refresh halaman
            return Redirect::to('admin/product/create')
            ->withErrors($validator);

        }else{

            $image=$request->file('imageFile')->store('productImages','public');
            
            $product=new \App\Product;

            $product->name=Input::get('name');
            $product->condition=Input::get('condition');
            $product->description=Input::get('description');
            $product->price=Input::get('price');
            $product->image=$image;
            $product->save();

            Session::flash('message','Product Stored');

            return "Berhasil Input Barang";
        }
    }

28. Sekarang coba input data pada form tambah data, lihat apakah berhasil

29. Buatlah sebuah file index.blade.php dalam folder product

30. Masukkan code di bawah ini ke dalam index.blade.php

@extends('admin/admin')
@section('content')
<div class="row">
    <div class="col-12">
        <div class="card">
            <div class="card-header">
                <h3 class="card-title">Data Barang</h3>
                <div class="card-tools">
                 <a href="{{ URL::to('/admin/product/create')}}" class="btn btn-tool">
                     <i class="fa fa-plus"></i>
                     &nbsp; Add
                 </a>
             </div>
         </div>
         <div class="card-body">
            @if (Session::has('message'))
            <div id="alert-msg" class="alert alert-success alert-dismissible">
                <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
                {{ Session::get('message') }}
            </div>
            @endif
            <div class="row">
                <div class="col-md-12">
                    <table class="table table-bordered table-hover">
                        <thead>
                            <tr class="text-center">
                                <th>ID</th>
                                <th>Nama</th>
                                <th>Harga</th>
                                <th>Deskripsi</th>
                                <th>Kondisi</th>
                                <th>Gambar</th>
                                <th>Aksi</th>
                            </tr>
                        </thead>
                        <tbody>
                            @foreach($products as $product)
                            <tr>
                                <td class="text-center">{{ $product['id'] }}</td>
                                <td>{{ $product['name'] }}</td>
                                <td>Rp. {{ $product['price'] }}</td>
                                <td>{{ $product['description'] }}</td>
                                <td>{{ $product['condition'] }}</td>
                                <td class="text-center"><img src="{{ asset('storage/'.$product['image']) }}" width="100"/></td>
                                <td class="text-center">
                                    <form method="POST" action="{{ URL::to('/admin/product/'.$product['id']) }}">
                                        {{ csrf_field() }}
                                        <input type="hidden" name="_method" value="DELETE" />
                                        <div class="btn-group">
                                            <a class="btn btn-info" href="{{ URL::to('/admin/product/'.$product['id']) }}"><i class="fa fa-eye"></i></a>
                                            <a class="btn btn-success" href="{{ URL::to('/admin/product/'.$product['id'].'/edit') }}"><i class="fa fa-pencil"></i></a>
                                            <button type="submit" class="btn btn-danger"><i class="fa fa-trash"></i></button>
                                        </div>
                                    </form>
                                </td>
                            </tr>
                            @endforeach
                        </tbody>
                    </table>


                </div>
            </div>
        </div>
    </div>
</div>
</div>

@endsection

31. Buka file ProductController.php tambahkan code dalam method index ( )

32. Sekarang coba buka di browser nya, masukkan http://localhost/LaraStore/public/admin/product/

33. Buka file ProductController.php ubah code dalam method store ( )

34. Buka file sidebar.blade.php ubah code seperti gambar di bawah

35. Sekarang kita akan menampilkan detail barang, buatlah sebuah file show.blade.php dalam folder product

36. Buka file show.blade.php tambahkan code di bawah

@extends('admin/admin')
@section('content')
    <div class="row">
        <div class="col-12">
            <div class="card">
                <div class="card-header">
                    <h3 class="card-title">Detail Barang</h3>
                </div>
                <div class="card-body">
                    <div class="row">
                        <div class="col-md-12">
                            <img src="{{ asset('storage/'.$product['image']) }}" 
                                height="200" width="100%"/>
                        </div>
                    </div>
                    <div class="row">
                        <div class="col-md-6">
                            
                            <div class="form-group">
                                <label for="name">Nama Barang</label>
                                <input id="name" type="text" value="{{ $product['name'] }}" class="form-control" disabled />
                            </div>
                            <div class="form-group">
                                <label for="price">Harga Barang</label>
                                <input id="price" type="text" value="{{ $product['price'] }}" class="form-control" disabled />
                            </div>
                        </div>
                        <div class="col-md-6">
                            <div class="form-group">
                                <label for="status">Kondisi Barang</label>
                                <input id="status" type="text" value="{{ $product['condition'] }}" class="form-control" disabled />
                            </div>
                        </div>
                    </div>
                    <div class="row">
                        <div class="col-md-12">
                            <div class="form-group">
                                <label for="description">Description</label>
                                <input id="description" type="text" value="{{ $product['description'] }}" class="form-control" disabled />
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
@endsection

37. Buka file ProductController.php tambahkan code dalam method show ( )

38. Klik simbol mata dalam kolom aksi pada salah satu data

39. Sekarang kita akan membuat form untuk edit data, buatlah sebuah file edit.blade.php dalam folder product

40. Buka file edit.blade.php tambahkan code di bawah

@extends('admin/admin')
@section('content')
<div class="row">
    <div class="col-12">
        {{ Form::model($product,['route'=>['product.update',$product['id']], 'files'=>true,'method'=>'PUT']) }}
        <div class="card">
            <div class="card-header">
                <h3 class="card-title">Ubah Data Barang</h3>
            </div>
            <div class="card-body">
                @if(!empty($errors->all()))
                <div class="alert alert-danger">
                    {{ Html::ul($errors->all())}}
                </div>
                @endif
                <div class="row">
                    <div class="col-md-12">
                        <img src="{{ asset('storage/'.$product['image'])}}" width="100%" height="200">
                    </div>
                    <div class="col-md-6">
                        <div class="form-group">
                            {{ Form::label('name', 'Nama Barang') }}
                            {{ Form::text('name', $product['name'], ['class'=>'form-control', 'placeholder'=>'Masukkan Nama Barang']) }}
                        </div>
                        <div class="form-group">
                            {{ Form::label('price', 'Harga Barang') }}
                            {{ Form::text('price', $product['price'], ['class'=>'form-control', 'placeholder'=>'Masukkan Harga Barang']) }}
                        </div>
                    </div>
                    <div class="col-md-6">
                        <div class="form-group">
                            {{ Form::label('condition', 'Kondisi Barang') }}
                            <select name="item_kind" class="form-control">
                                <option value="baru" {{ $product['condition']=='baru'?'selected':'' }}>Baru</option>
                                <option value="bekas" {{ $product['condition']=='bekas'?'selected':'' }}>Bekas</option>
                            </select>        
                        </div>
                        <div class="form-group">
                            {{ Form::hidden('imagePath',$product['image'])}}
                            {{ Form::label('image', 'Image') }}
                            {{ Form::file('imageFile', ['class'=>'form-control']) }}        
                        </div>
                    </div>
                </div>
                <div class="row">
                    <div class="col-12">
                        {{ Form::label('description', 'Description') }}
                        {{ Form::textarea('description', $product['description'], ['class'=>'form-control', 'placeholder'=>'Enter description', 'rows'=>5]) }}
                    </div>
                </div>
            </div>
            <div class="card-footer">
                <a href="{{ URL::to('admin/product') }}" class="btn btn-outline-info">Back</a>
                {{ Form::submit('Proses', ['class' => 'btn btn-primary pull-right']) }}
            </div>
        </div>
        <!-- </form> -->
        {{ Form::close() }}
    </div>
</div>
@endsection

41. Buka file ProductController.php tambahkan code dalam method edit ( )

42. Klik simbol pensil pada kolom aksi

43. Buka file ProductController.php tambahkan code dalam method update ( )

public function update(Request $request, $id)
    {
        //
        $rules=[
            
            'name'=>'required',
            'price'=>'required|integer',
            'description'=>'required',
        ];

        $pesan=[
            'name.required'=>'Nama Tidak Boleh Kosong!!',
            'price.required'=>'Harga Tidak Boleh Kosong!!',
            'description.required'=>'Deskripsi Barang Tidak Boleh Kosong!!',
        ];


        $validator=Validator::make(Input::all(),$rules,$pesan);

        if ($validator->fails()) {
            return Redirect::to('admin/product/'.$id.'/edit')
            ->withErrors($validator);

        }else{

            $image="";

            if (!$request->file('imageFile')) {
                # code...
                $image=Input::get('imagePath');
            }else{
                $image=$request->file('imageFile')->store('productImages','public');                
            }

            $product=\App\Product::find($id);

            $product->name=Input::get('name');
            $product->condition=Input::get('condition');
            $product->price=Input::get('price');
            $product->description=Input::get('description');
            $product->image=$image;
            $product->save();

            Session::flash('message','Data Barang Berhasil Diubah');
            
            return Redirect::to('admin/product');
        }
    }

44. Sekarang coba anda ubah salah satu data barang

45. Terakhir kita aktifkan fungsi hapus, buka file ProductController.php tambahkan code dalam method delete ( )

46. Coba hapus salah satu data dengan klik simbol tong sampah



Membuat Login Form Dengan Codeigniter

Pada tutorial kali ini, kita akan coba membuat login form dengan codeigniter. Berikut ini adalah bahan yang perlu kita persiapkan :

  1. Download framework codeigniter disini
  2. Pastikan anda telah berhasil menjalankan server local seperti Xampp dan database MySQL
  3. Kemudian ekstrak hasil downloadan framework diatas dan beri nama folder tutorialrumahcoding, kemudian letakkan didalam folder xampp/htdocs/
  4. Buat sebuah database dengan nama tutorial_rumah_coding dan buat tabel sebagai berikut :

Setelah persiapan selesai, saatnya kita mulai bermain dengan codeigniter. Langkah pertama, buat sebuah controller dengan nama User.php pada folder application/controllers/. Berikut adalah isi perintah dari controller User.php :

<?php
class User extends CI_Controller{
  public function __construct(){
  parent::__construct();
  $this-&gt;load-&gt;database();
  $this-&gt;load-&gt;helper('url');
 }

 public function login(){

   if($this-&gt;input-&gt;post('login')){
     $email = $this-&gt;input-&gt;post('email');
     $password = $this-&gt;input-&gt;post('pass');

     $que=$this-&gt;db-&gt;query("select * from siswa where email='".$email."' and password='$password'");
     $row = $que-&gt;num_rows();
     if($row){
       redirect('User/dashboard');
     }
     else{
       $data['error']="<h3 style='color:red'&gt;Invalid login details</h3&gt;";
     }
   }
   $this-&gt;load-&gt;view('login',$data);
  }

 function dashboard(){
   $this-&gt;load-&gt;view('dashboard');
 }
}
?&gt;

Perhatikan pada fungsi __construct diatas, kita melakukan load terhadap library database dan helper url. Pada script diatas terdapat dua view yang akan kita panggil, yaitu view form login dan view dashboard jika berhasil login. Tapi sebelum membuat kedua view diatas, kita perlu menghubungkan project kita dengan database dan melakukan pengaturan base_url() yang terletak dalam file config/config.php sebagai berikut :

Selanjutnya lakukan pengaturan pada file config/database.php agar project codeigniter terhubung dengan database yang telah kita buat sebelumnya. Adapun pengaturannya adalah sebagai berikut :

Untuk nilai password, defaultnya adalah ‘ ‘. Berhubung database saya telah ditambahkan password maka harap sesuaikan password yang diinginkan. Selanjutnya buat tampilan view login.php pada folder application/views/ dengan perintah berikut ini:

<!DOCTYPE html&gt;
<html&gt;
<head&gt;
<title&gt;Login form</title&gt;
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"&gt;
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"&gt;</script&gt;
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"&gt;</script&gt;
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"&gt;</script&gt;
<style &gt;
  .jumbotron{
    border-bottom-left-radius: 600px;
    border-bottom-right-radius: 600px;
    background-color: pink;

  }

</style&gt;
</head&gt;

<body style="background-color:black"&gt;
<div class="container jumbotron"  &gt;
  <div class="row" style="margin-top: 80px"&gt;
    <div class="col-md-3"&gt;

    </div&gt;
      <div class="col-md-6 "&gt;
        <form method="post"&gt;
         <div class="form-group"&gt;
           <label for="exampleInputEmail1"&gt;Email address</label&gt;
           <input type="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" placeholder="Enter email"  name="email"&gt;
         </div&gt;
         <div class="form-group"&gt;
           <label for="exampleInputPassword1"&gt;Password</label&gt;
           <input type="password" class="form-control" id="exampleInputPassword1" placeholder="Password"  name="pass"&gt;
         </div&gt;
         <div class="row"&gt;
           <div class="col-md-5"&gt;

           </div&gt;
           <div class="col-md-2"&gt;
             <input type="submit" class="btn btn-primary"  name="login"  value="Login" &gt;</input&gt;
           </div&gt;
           <div class="col-md-5"&gt;

           </div&gt;
         </div&gt;
       </form&gt;
      </div&gt;
      <div class="col-md-3"&gt;

      </div&gt;
  </div&gt;

</div&gt;


</body&gt;
</html&gt;

Langkah terakhir adalah membuat view dashboard.php didalam folder application/views/ dengan perintah sebagai berikut:

<!DOCTYPE html&gt;
<html lang="en"&gt;
  <head&gt;
    <meta charset="utf-8"&gt;
    <meta http-equiv="X-UA-Compatible" content="IE=edge"&gt;
    <meta name="viewport" content="width=device-width, initial-scale=1"&gt;
    <title&gt;</title&gt;

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"&gt;
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"&gt;</script&gt;
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"&gt;</script&gt;
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"&gt;</script&gt;

  </head&gt;
  <body&gt;
    <div class="container"&gt;
      <div class="row"&gt;
        <div class="col-md-12"&gt;
            <h1 class="jumbotron text-center"&gt;Selamat Datang Admin</h1&gt;
        </div&gt;
      </div&gt;
    </div&gt;

  </body&gt;
</html&gt;

Apabila aplikasi kita jalankan melalui url http://localhost/tutorialrumahcoding/index.php/user/login. pengguna memasukkan password dan email yang sebelumnya telah tersimpan didatabase kita. Apabila inputan pengguna ditemukan dengan data yang ada didatabase kita, maka pengguna akan diarahkan ke view atau halaman dashboard, jika tidak/gagal login maka aplikasi akan menampilkan message error “invalid login details”, karena itu pastikan sebelumnya kita telah memasukkan data kedalam database yang telah dibuat seperti contoh dibawah ini :

Membuat Aplikasi CRUD Sederhana di Android Menggunakan PHP dan MySQL PART 4

  1. Masuk ke file FormActivity.java , kemudian isi dengan source code di bawah
    public class FormActivity extends AppCompatActivity {
    
        @BindView(R.id.et_name)
        EditText etName;
        @BindView(R.id.et_contact_number)
        EditText etContactNumber;
        @BindView(R.id.btn_simpan)
        Button btnSimpan;
    
        int personId;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_form);
    
            ButterKnife.bind(this);
            personId=getIntent().getIntExtra("id",0);
    
            if (personId &amp;gt; 0) {
                getPerson(generateToken(), personId);
    
            }
    
        }
    
        @OnClick(R.id.btn_simpan)
        public void onClick(View view) {
            int getId = view.getId();
            switch (getId) {
                case R.id.btn_simpan:
                    if (personId > 0) {
                        updatePerson(personId, etName.getText().toString(), etContactNumber.getText().toString());
                    } else {
                        setPerson(etName.getText().toString(), etContactNumber.getText().toString());
    
                    }
                    break;
    
            }
        }
    
        public void setPerson(String name, String contactNumber) {
    
            ApiEndPoint apiEndPoint = ApiClient.getClient().create(ApiEndPoint.class);
            Call<StatusResponse> call = apiEndPoint.createRequest(name, contactNumber);
    
            call.enqueue(new Callback<StatusResponse>() {
                @Override
                public void onResponse(Call<StatusResponse> call, Response<StatusResponse> response) {
    
                    final StatusResponse statusResponse = response.body();
    
                    if (statusResponse != null) {
                        Log.d("Response Data ", "Total Data" + statusResponse.getStatus());
                        if (statusResponse.getStatus()) {
                            finish();
                            Toast.makeText(getApplicationContext(), "Data Berhasil Di Tambah", Toast.LENGTH_SHORT).show();
                        } else {
                            Toast.makeText(getApplicationContext(), "Data Kosong", Toast.LENGTH_SHORT).show();
                        }
    
                    } else {
                        Log.d("Login : ", "Data Null");
                    }
                }
    
                @Override
                public void onFailure(Call<StatusResponse> call, Throwable t) {
                    Toast.makeText(getApplicationContext(), "Koneksi Bermasalah", Toast.LENGTH_SHORT).show();
    
                }
            });
        }
    
        private String generateToken() {
    
            SecureRandom random = new SecureRandom();
            byte bytes[] = new byte[20];
            random.nextBytes(bytes);
            return bytes.toString();
        }
    
        public void getPerson(final String token, int id) {
    
            ApiEndPoint apiEndPoint = ApiClient.getClient().create(ApiEndPoint.class);
            Call<ReadResponse> call = apiEndPoint.readPersonRequest(token, id);
    
            call.enqueue(new Callback<ReadResponse>() {
                @Override
                public void onResponse(Call<ReadResponse> call, Response<ReadResponse> response) {
    
                    final ReadResponse readResponse = response.body();
    
                    if (readResponse != null) {
                        Log.d("Response Data ", "Total Data" + readResponse.getStatus());
                        if (readResponse.getStatus()) {
    
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
    
                                    List<Person> person = readResponse.getPersons();
    
                                    etName.setText(person.get(0).getPersonName());
                                    etContactNumber.setText(person.get(0).getContactNumber());
                                }
                            });
    
                        } else {
                            Toast.makeText(getApplicationContext(), "Data Kosong", Toast.LENGTH_SHORT).show();
                        }
    
                    } else {
                        Log.d("Login : ", "Data Null");
                    }
                }
    
                @Override
                public void onFailure(Call<ReadResponse> call, Throwable t) {
                    Toast.makeText(getApplicationContext(), "Koneksi Bermasalah", Toast.LENGTH_SHORT).show();
    
                }
            });
        }
    
        public void updatePerson(int id, String name, String contactNumber) {
    
            ApiEndPoint apiEndPoint = ApiClient.getClient().create(ApiEndPoint.class);
            Call<StatusResponse> call = apiEndPoint.updateRequest(id, name, contactNumber);
    
            call.enqueue(new Callback<StatusResponse>() {
                @Override
                public void onResponse(Call<StatusResponse> call, Response<StatusResponse> response) {
    
                    final StatusResponse statusResponse = response.body();
    
                    if (statusResponse != null) {
                        Log.d("Response Data ", "Total Data" + statusResponse.getStatus());
                        if (statusResponse.getStatus()) {
                            finish();
                            Toast.makeText(getApplicationContext(), "Data Berhasil Di Ubah", Toast.LENGTH_SHORT).show();
                        } else {
                            Toast.makeText(getApplicationContext(), "Data Kosong", Toast.LENGTH_SHORT).show();
                        }
    
                    } else {
                        Log.d("Login : ", "Data Null");
                    }
                }
    
                @Override
                public void onFailure(Call<StatusResponse> call, Throwable t) {
                    Toast.makeText(getApplicationContext(), "Koneksi Bermasalah", Toast.LENGTH_SHORT).show();
    
                }
            });
        }
    
    }
    
  2. Sekarang kita buat menu untuk menampilkan Form Input Data. Buat sebuah folder dengan nama menu di dalam res.
  3. Klik kanan pada folder menu , lalu buat file tambah_data.xml .
  4. Lalu masuk ke app > res > menu > tambah_data.xml . Masukkan source code di bawah
    <?xml version="1.0" encoding="utf-8"?>
    <menu xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">
    
        <item
            android:id="@+id/menu_create"
            android:icon="@mipmap/ic_launcher"
            android:title="Create"
            app:showAsAction="always" />
    
    </menu>
    
  5. Lalu masuk ke file MainActivity.java . Tambahkan 2 fungsi di bawah.
  6. Sekarang kita coba running ulang aplikasi, lalu sentuh Kotak Hijau. Nanti akan tampil form input data. Coba input satu data, lalu sentuh Tombol Simpan.                                                                                                               
  7. Buat menu resource seperti cara no 3, namakan dengan context_menu. Kemudian tambahkan 2 item menu seperti gambar di bawah.
  8. Sekarang kita aktifkan context menu untuk memunculkan menu Edit dan Delete. Masuk ke file MainActivity.java . Tambahkan 2 fungsi di bawah.
  9. Daftarkan context menu ke ListView dengan memanggil fungsi registerForContextMenu().
  10. Sekarang coba running kembali , lalu sentuh dan tahan pada data. Nanti akan muncul menu 
  11. Tambahkan fungsi hapus pada MainActivity Class, masukkan source code berikut.
    public void deletePerson(final int id) {
    
            ApiEndPoint apiEndPoint = ApiClient.getClient().create(ApiEndPoint.class);
            Call<StatusResponse> call = apiEndPoint.deleteRequest(id);
    
            call.enqueue(new Callback<StatusResponse>() {
                @Override
                public void onResponse(Call<StatusResponse> call, Response<StatusResponse> response) {
    
                    final StatusResponse StatusResponse = response.body();
    
                    if (StatusResponse != null) {
                        Log.d("Response Data ", "Total Data" + StatusResponse.getStatus());
                        if (StatusResponse.getStatus()) {
    
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    Toast.makeText(getApplicationContext(), "Data Berhasil Dihapus", Toast.LENGTH_SHORT).show();
                                    getAllPerson(generateToken());
                                }
                            });
    
                        } else {
                            Toast.makeText(getApplicationContext(), "Data Kosong", Toast.LENGTH_SHORT).show();
                        }
    
                    } else {
                        Log.d("Login : ", "Data Null");
                    }
                }
    
                @Override
                public void onFailure(Call<StatusResponse> call, Throwable t) {
                    Toast.makeText(getApplicationContext(), "Koneksi Bermasalah", Toast.LENGTH_SHORT).show();
    
                }
            });
        }
    
  12. Sekarang kita tambahkan code untuk mengambil data Person Id. Lalu panggil fungsi deletePerson .
  13. Selanjutnya, kita tambahkan code untuk pindah activity, serta mengirim nilai Person Id.
  14. Sekarang coba anda hapus dan ubah data melalui menu. Kalau berhasil, it’s done yea ……

Workshop Android Spesial Ramadhan

Bulan Ramadhan sebentara lagi datang, apa yang sudah anda persiapkan? Bulan Ramadhan kali ini, Rumah Coding insya Allah akan mengadakan “Workshop Android Spesial Ramadhan”. Terdapat 3 workshop di bulan ramadhan mendatang. Melalui workshop ini, anda akan langsung praktek membuat aplikasi berikut

1. Kamus Arab Indonesia
Hari: Minggu,
Tanggal: 28 Mei 2017
Waktu: 09:00 – 17:00
Biaya: Rp. 100.000

Materi:
– Activity
– Frame Layout
– Google Translator API
– List View
– Card View
– Custom Adapter
– Share Intent
– Realm

2. Jadwal dan Pengingat Shalat
Hari: Kamis,
Tanggal: 1 Juni 2017
Waktu: 09:00 – 17:00
Biaya: Rp. 100.000

Materi:
– OkHttp
– Custom Drawable
– Shared Preferences
– Notification
– Task Schedule
– Sound

3. App Al-Qur’an
Hari: Minggu,
Tanggal: 4 Juni 2017
Waktu: 09:00 – 17:00
Biaya: Rp. 100.000

Materi:
– OkHttp
– Image View
– View Pager
– Realm
– List View
– Custom Adapter

Tempat: DILo (Digital Innovation Longue ) Depok
Jl. Margonda Raya No. 23 (Rukan Sebelah BPJS Kesehatan Kota Depok),
Kel. Depok, Kec. Pancoran MAS, Depok, Pancoran MAS, Kota Depok, Jawa Barat 16431
https://goo.gl/maps/2cb1AZBRGZQ2

Persyaratan:
1. Memiliki laptop sendiri (Windows/Linux/Mac 4GB RAM)

Persyaratan Software:
1. JDK7 (https://goo.gl/8XHlU2)
2. Android Studio (https://goo.gl/fcKQbF)
3. Emulator: Blue Stack (www.bluestacks.com)

Tahap pendaftaran:
1. Mengisi formulir di bawah.
2. Peserta akan dihubungi melalui email/whatsapp
3. Pembayaran via transfer
4. Workshop.

Fasilitas:
1. Sertifikat
2. Ruangan Full AC

Catatan:
– Tersedia koneksi internet, tetapi untuk berjaga-jaga, silahkan mempersiapkan koneksi internet masing-masing.

Informasi:
087876335618
[email protected]

 

Silahkan lengkapi formulir pendaftaran di bawah ini:

Drawing Mandelbrot Set on HTML5 Graphics Canvas

Mandelbrot set is a mathematical set of points whose boundary is a distinctive and easily recognizable two-dimensional fractal shape. The Mandelbrot set is defined over the complex number plane. The definition of the Mandelbrot set is simple but the structure of the set is really complex and beautiful.

Mandelbrot Set Overview

Mandelbrot set is defined mathematically as the set of values of c in the complex plane for which the orbit of 0 under iteration of the complex quadratic polynomial zn+1 = zn2 + c remains bounded. That is, a complex number c is part of the Mandelbrot set if, when starting with z0 = 0 and applying the iteration repeatedly, the absolute value of zn remains bounded however large n gets.

Below is the structure of the Mandelbrot set that is generated using our application.

Mandelbrot Set
Mandelbrot Set

HTML 5 Canvas Overview

HTML5 is the latest version of the standard HTML. It comes with new cool element, Canvas that allows you to draw directly and manipulate every single pixels in the canvas. A canvas is a rectangular area on an HTML page, and it is specified with the [cci][/cci] element. HTML5 currently is under development and not all browser support it yet.

We’ll not cover all the definition of cool function in the canvas. There are documentation of those over the web. We only give an attention to several functions that will be used in our tutorial.

Every canvas element has a graphics context that will be used to modify the pixel on the canvas. We’ll use [cci]2d[/cci] context. To get the context, use [cci]getContext[/cci] function of the canvas object.

var canvas = document.getElementById('thecanvas');
var ctx = canvas.getContext('2d');

The above code assumes that we have defined a canvas element which id [cci]thecanvas[/cci].

<canvas id="thecanvas" width="500" height="500"></canvas>

Our requirement is to get all the pixels data of the canvas and modify the color of the pixels. To get all pixels data, use [cci]getImageData[/cci] function of the context. The function has 4 arguments [cci]x[/cci],[cci]y[/cci],[cci]width[/cci] and [cci]height[/cci]. [cci]x[/cci] and [cci]y[/cci] arguments define the square top left position from which the pixels will be taken. [cci]width[/cci] and [cci]height[/cci] define the dimension of the square.

var imageData = ctx.getImageData(0, 0, 100, 100);
var pixels = imageData.data;

The variable [cci]pixels[/cci] above contains 100×100=10.000 pixels that is save in 1 dimension array. 1 pixels have 4 elements, red,green,blue and alpha component. So [cci]pixels[/cci] variable has 10.000×4 = 40.000 elements. 1 element pixel is an integer from 0 to 255.

We now can modify the pixels data. After the pixels have been modified, we must put the pixels back to canvas in order to our modification takes effect.

ctx.putImageData(imageData, 0, 0);

Drawing Mandelbrot Set on HTML 5 Canvas

Javascript doesn’t provides built in complex number data type. So, we have to define our complex number data type. For simplicity of the tutorial, we will represent any complex number in javascript object with two properties. The [cci]x[/cci] property represents the real part and [cci]y[/cci] property represents the imaginary part.

//define complex data type
var Complex = function(x, y) {
   this.x = x; // real part
   this.y = y; // imaginary part
};

//define new complex number 1+2i
var complex = new Complex(1,2);

We have now a simple complex number data type for our application. Before we start to code, remember from above explanation. The mandelbrot definition requires to use two operation on complex number. We’ll not define all number operations in complex number, but we’ll create only two operations, multiplication and addition that will be used in generating mandelbrot set.

//define two complex number
var a = 1, b = 2, c = 3, d = 4;
var complex1 = new Complex(a,b);
var complex1 = new Complex(c,d);

//add complex1 and complex1 will result
var addition = new Complex(a+c, b+d);

//multiply complex1 and complex 2 will result
var multiplication = new Complex(a*c - b*d, b*c + a*d);

 

The Mandelbrot Set Drawing Algorithm

We’ll use different approach from mandelbrot set definition to visualize the set. Rather than finding all complex numbers [cci]c[/cci] which is bounded, our goal is to colorize all of the pixels in the canvas based on number of iterations. This will result great visualization for mandelbrot set.

Step by Step Mandelbrot Set Drawing

  1. Define user interface. Our application will has simple user interface. It’ll contains color scheme selection box, a button and the canvas.

    Mandelbrot Generator Simple User Interface
    Mandelbrot Generator Simple User Interface

    Below is HTML tags that defines our simple user interface.

<html>
<head>
<title>Drawing Mandelbrot set on HTML5 graphics canvas</title>
</head>
<body onload="setupCanvas();">
    
<div style="margin:0 auto;width:505px;padding-top:10px;">

<div>Color Scheme:
        <select id="scheme">
<option value="1" selected>Color Scheme 1</option>
<option value="2">Color Scheme 2</option>
<option value="3">Color Scheme 3</option>
<option value="4">Color Scheme 4</option>
<option value="5">Color Scheme 5</option>
<option value="6">Color Scheme 6</option>
        </select>
        <input type="button" value="Render" id="render_btn" onclick="render()"/>
        Scroll your mouse on the canvas to zoomin/zoomout
        </div>

        <canvas style="border:1px solid;" id="thecanvas" width="500" height="500"></canvas>
    </div>

</body>
</html>

After the html page is loaded, immediately we call javascript function [cci]setupCanvas[/cci]. This function will checks whether the browser support html5 canvas then get canvas’s drawing context and save it as global variable [cci]ctx[/cci]. We’ll use the context to modify each pixels on the canvas.

  • Define [cci]setupCanvas[/cci] function.
         
    var setupCanvas = function() {
        canvas = document.getElementById('thecanvas');
        setupMouseListener();
    
        if (!canvas.getContext) {
            alert("I'm sorry, seems your browser not support HTML 5, try another browser.");
            return;
        }
           
        // get drawing context
        ctx = canvas.getContext('2d');
    };   
    
  • Define render function.
    In this function we get the selected color scheme in the selection box. Save the canvas size as global variables then define the scaling ratio from canvas coordinats to mandelbrot coordinats.

 

var render = function() {
    if (!canvas.getContext) return;
    
    //get color scheme
    var a = document.getElementById('scheme');
    colorScheme = parseInt((a.value || a.options[a.selectedIndex].value));
    
    //save canvas size into variable
    cw = canvas.width;
    ch = canvas.height;
    
    //define scaling ratio from canvas coordinat to mandlebort coordinat
    scaleX = (mx[1] - mx[0])/cw;
    scaleY = (my[1] - my[0])/ch;
    
    drawMandlebrot();
};
  • Define the [cci]drawMandelbrot[/cci] function.
    In this function, we iterate to each pixels in the canvas and find the iteration for each pixels then color the pixel based on number iterations.

    var drawMandlebrot = function() {
        if(isDrawing) return;
        
        isDrawing = true;
        
        var imageData = ctx.getImageData(0, 0, cw, ch);
        pixels = imageData.data;
        
        for(var x = 0; x < cw; x++) {
            for(var y = 0; y < ch; y++) {
                iteration = 0;
                // scale canvas coordinat to mandlebrot complex coordinat
                var x0 = scaleX*x + mx[0], y0 = scaleY*y + my[0];
                // define complex number c
                var c = new Complex(x0, y0), z = new Complex(0, 0);
                
                while(iteration < maxIteration) { // check if z still inbound if(z.x*z.x + z.y*z.y >= 2*2) {
                        break;
                    }
                    
                    // multiply z and z
                    z = new Complex(z.x*z.x - z.y*z.y, z.y*z.x + z.x*z.y);
                    // add z and c
                    z = new Complex(z.x+c.x, z.y+c.y);
                    // inrease iteration
                    iteration++;
                }
                
                // colorize current pixel
                setPixelColor(x, y, iteration);
            }
        }
        
        ctx.putImageData(imageData, 0, 0);
        isDrawing = false;
    };        
    
  • Define [cci]setPixelColor[/cci]
    This function will color the current pixels and get the color from [cci]getColor[/cci] function. [cci]getColor[/cci] function will generate a color based on number of iteration and selected color scheme.

    var getColor = function(i) {            
        i /= maxIteration;
        var cr = 0.0;
        var cg = 0.0;
        var cb = 0.0;
        
        switch(colorScheme) {
            case 1:
                if (i >= 0.66) cr = i;
                else if (i >= 0.33) cg = i;
                else cb = i;
                break;
            case 2:
                if (i >= 0.66) cr = i;
                else if (i >= 0.33) cb = i;
                else cg = i;
                break;
            case 3:
                if (i >= 0.66) cb = i;
                else if (i >= 0.33) cg = i;
                else cr = i;
                break;
            case 4:
                if (i >= 0.66) cg = i;
                else if (i >= 0.33) cr = i;
                else cb = i;
                break;
            case 5:
                if (i >= 0.66) cg = i;
                else if (i >= 0.33) cb = i;
                else cr = i;
                break;
            case 6:
                if (i >= 0.66) cb = i;
                else if (i >= 0.33) cr = i;
                else cg = i;
                break;
        };            
        
        var r = parseInt(cr * 3 * maxColor);
        var g = parseInt(cg * 3 * maxColor);
        var b = parseInt(cb * 3 * maxColor);
        return [r, g, b];
    };
    var setPixelColor = function(x, y, i) {
        var c = getColor(i);
        var off = 4 * (y * cw + x);
        pixels[off] = c[0]; //red
        pixels[off + 1] = c[1]; //green
        pixels[off + 2] = c[2]; //blue
        pixels[off + 3] = 255; //alpha
    };
    
  • Finally, add the zoom capability.
    var mouseWheelHandler = function(e) {
        // cross-browser wheel delta
        var e = window.event || e; // old IE support
        // get delta scroll
        var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
        
        //get mouse position
        var mousePos = getMousePos(e);
        
        // scale canvas coordinat to mandlebrot complex coordinat
        var x0 = scaleX*mousePos.x + mx[0], y0 = scaleY*mousePos.y + my[0];
        
        //scale the mandelbrot coordinat size
        var scale = 1 - delta*zoomScale;
        var sizeX = (mx[1]-mx[0])*scale;
        var sizeY = (my[1]-my[0])*scale;
        
        // redefine mandelbrot boundaries
        mx = [x0-sizeX/2, x0+sizeX/2];
        my = [y0-sizeY/2, y0+sizeY/2];
        render();
    };        
    var getMousePos = function(evt) {
        var rect = canvas.getBoundingClientRect();
        return {
            x: evt.clientX - rect.left,
            y: evt.clientY - rect.top
        };
    };
    

Final Source Code

<html>
<head>
    <title>Drawing Mandelbrot set on HTML5 graphics canvas</title>
    <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20type%3D%22text%2Fjavascript%22%3E%0A%20%20%20%20%20%20%20%20var%20canvas%2C%20ctx%3B%0A%20%20%20%20%20%20%20%20var%20iteration%2C%20maxIteration%20%3D%20100%2C%20maxColor%20%3D%20255%3B%0A%20%20%20%20%20%20%20%20var%20cw%2C%20ch%2C%20scaleX%2C%20scaleY%3B%0A%20%20%20%20%20%20%20%20var%20zoomScale%20%3D%200.3%3B%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%2F%2F%20color%20schemes%0A%20%20%20%20%20%20%20%20var%20colorScheme%20%3D%201%3B%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%2F%2Fdefine%20mandlebort%20boundaries%0A%20%20%20%20%20%20%20%20var%20mx%20%3D%20%5B-2%2C2%5D%2C%20my%20%3D%20%5B-2%2C2%5D%3B%0A%20%20%20%20%20%20%20%20%2F%2F%20hold%20all%20pixels%20image%20data%0A%20%20%20%20%20%20%20%20var%20pixels%3B%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20var%20isDrawing%20%3D%20false%3B%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%2F%2Fdefine%20complex%20data%20type%0A%20%20%20%20%20%20%20%20var%20Complex%20%3D%20function(x%2C%20y)%20%7B%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20this.x%20%3D%20x%3B%20%2F%2F%20real%20part%0A%20%20%20%20%20%20%20%20%20%20%20%20this.y%20%3D%20y%3B%20%2F%2F%20imaginary%20part%0A%20%20%20%20%20%20%20%20%7D%3B%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20var%20setupCanvas%20%3D%20function()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20canvas%20%3D%20document.getElementById('thecanvas')%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20setupMouseListener()%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!canvas.getContext)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alert(%22I'm%20sorry%2C%20seems%20your%20browser%20not%20support%20HTML%205%2C%20try%20another%20browser.%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20get%20drawing%20context%0A%20%20%20%20%20%20%20%20%20%20%20%20ctx%20%3D%20canvas.getContext('2d')%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20render()%3B%0A%20%20%20%20%20%20%20%20%7D%3B%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20var%20render%20%3D%20function()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!canvas.getContext)%20return%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2Fget%20color%20scheme%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20a%20%3D%20document.getElementById('scheme')%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20colorScheme%20%3D%20parseInt((a.value%20%7C%7C%20a.options%5Ba.selectedIndex%5D.value))%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2Fsave%20canvas%20size%20into%20variable%0A%20%20%20%20%20%20%20%20%20%20%20%20cw%20%3D%20canvas.width%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20ch%20%3D%20canvas.height%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2Fdefine%20scaling%20ratio%20from%20canvas%20coordinat%20to%20mandlebort%20coordinat%0A%20%20%20%20%20%20%20%20%20%20%20%20scaleX%20%3D%20(mx%5B1%5D%20-%20mx%5B0%5D)%2Fcw%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20scaleY%20%3D%20(my%5B1%5D%20-%20my%5B0%5D)%2Fch%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20drawMandlebrot()%3B%0A%20%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%20%20%20%20var%20drawMandlebrot%20%3D%20function()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if(isDrawing)%20return%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20isDrawing%20%3D%20true%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20imageData%20%3D%20ctx.getImageData(0%2C%200%2C%20cw%2C%20ch)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20pixels%20%3D%20imageData.data%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20for(var%20x%20%3D%200%3B%20x%20%3C%20cw%3B%20x%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for(var%20y%20%3D%200%3B%20y%20%3C%20ch%3B%20y%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20iteration%20%3D%200%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20scale%20canvas%20coordinat%20to%20mandlebrot%20complex%20coordinat%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20var%20x0%20%3D%20scaleX*x%20%2B%20mx%5B0%5D%2C%20y0%20%3D%20scaleY*y%20%2B%20my%5B0%5D%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20define%20complex%20number%20c%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20var%20c%20%3D%20new%20Complex(x0%2C%20y0)%2C%20z%20%3D%20new%20Complex(0%2C%200)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20while(iteration%20%3C%20maxIteration)%20%7B%20%2F%2F%20check%20if%20z%20still%20inbound%20if(z.x*z.x%20%2B%20z.y*z.y%20%3E%3D%202*2)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20multiply%20z%20and%20z%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20z%20%3D%20new%20Complex(z.x*z.x%20-%20z.y*z.y%2C%20z.y*z.x%20%2B%20z.x*z.y)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20add%20z%20and%20c%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20z%20%3D%20new%20Complex(z.x%2Bc.x%2C%20z.y%2Bc.y)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20inrease%20iteration%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20iteration%2B%2B%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20colorize%20current%20pixel%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20setPixelColor(x%2C%20y%2C%20iteration)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20ctx.putImageData(imageData%2C%200%2C%200)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20isDrawing%20%3D%20false%3B%0A%20%20%20%20%20%20%20%20%7D%3B%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20var%20getColor%20%3D%20function(i)%20%7B%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20i%20%2F%3D%20maxIteration%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20cr%20%3D%200.0%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20cg%20%3D%200.0%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20cb%20%3D%200.0%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20switch(colorScheme)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20case%201%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(i%20%3E%3D%200.66)%20cr%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20else%20if%20(i%20%3E%3D%200.33)%20cg%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20else%20cb%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20case%202%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(i%20%3E%3D%200.66)%20cr%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20else%20if%20(i%20%3E%3D%200.33)%20cb%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20else%20cg%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20case%203%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(i%20%3E%3D%200.66)%20cb%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20else%20if%20(i%20%3E%3D%200.33)%20cg%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20else%20cr%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20case%204%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(i%20%3E%3D%200.66)%20cg%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20else%20if%20(i%20%3E%3D%200.33)%20cr%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20else%20cb%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20case%205%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(i%20%3E%3D%200.66)%20cg%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20else%20if%20(i%20%3E%3D%200.33)%20cb%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20else%20cr%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20case%206%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(i%20%3E%3D%200.66)%20cb%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20else%20if%20(i%20%3E%3D%200.33)%20cr%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20else%20cg%20%3D%20i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%3B%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20r%20%3D%20parseInt(cr%20*%203%20*%20maxColor)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20g%20%3D%20parseInt(cg%20*%203%20*%20maxColor)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20b%20%3D%20parseInt(cb%20*%203%20*%20maxColor)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20%5Br%2C%20g%2C%20b%5D%3B%0A%20%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%20%20%20%20var%20setPixelColor%20%3D%20function(x%2C%20y%2C%20i)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20c%20%3D%20getColor(i)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20off%20%3D%204%20*%20(y%20*%20cw%20%2B%20x)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20pixels%5Boff%5D%20%3D%20c%5B0%5D%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20pixels%5Boff%20%2B%201%5D%20%3D%20c%5B1%5D%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20pixels%5Boff%20%2B%202%5D%20%3D%20c%5B2%5D%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20pixels%5Boff%20%2B%203%5D%20%3D%20255%3B%0A%20%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%20%20%20%20var%20setupMouseListener%20%3D%20function()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(canvas.addEventListener)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20IE9%2C%20Chrome%2C%20Safari%2C%20Opera%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20canvas.addEventListener(%22mousewheel%22%2C%20mouseWheelHandler%2C%20false)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20Firefox%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20canvas.addEventListener(%22DOMMouseScroll%22%2C%20mouseWheelHandler%2C%20false)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20IE%206%2F7%2F8%0A%20%20%20%20%20%20%20%20%20%20%20%20else%20canvas.attachEvent(%22onmousewheel%22%2C%20mouseWheelHandler)%3B%0A%20%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%20%20%20%20var%20mouseWheelHandler%20%3D%20function(e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20cross-browser%20wheel%20delta%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20e%20%3D%20window.event%20%7C%7C%20e%3B%20%2F%2F%20old%20IE%20support%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20get%20delta%20scroll%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20delta%20%3D%20Math.max(-1%2C%20Math.min(1%2C%20(e.wheelDelta%20%7C%7C%20-e.detail)))%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2Fget%20mouse%20position%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20mousePos%20%3D%20getMousePos(e)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20scale%20canvas%20coordinat%20to%20mandlebrot%20complex%20coordinat%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20x0%20%3D%20scaleX*mousePos.x%20%2B%20mx%5B0%5D%2C%20y0%20%3D%20scaleY*mousePos.y%20%2B%20my%5B0%5D%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2Fscale%20the%20mandelbrot%20coordinat%20size%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20scale%20%3D%201%20-%20delta*zoomScale%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20sizeX%20%3D%20(mx%5B1%5D-mx%5B0%5D)*scale%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20sizeY%20%3D%20(my%5B1%5D-my%5B0%5D)*scale%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20redefine%20mandelbrot%20boundaries%0A%20%20%20%20%20%20%20%20%20%20%20%20mx%20%3D%20%5Bx0-sizeX%2F2%2C%20x0%2BsizeX%2F2%5D%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20my%20%3D%20%5By0-sizeY%2F2%2C%20y0%2BsizeY%2F2%5D%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20render()%3B%0A%20%20%20%20%20%20%20%20%7D%3B%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20var%20getMousePos%20%3D%20function(evt)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20rect%20%3D%20canvas.getBoundingClientRect()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20x%3A%20evt.clientX%20-%20rect.left%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20y%3A%20evt.clientY%20-%20rect.top%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="&lt;script&gt;" title="&lt;script&gt;" />
</head>
<body onload="setupCanvas();">
    
<div style="margin:0 auto;width:505px;padding-top:10px;">

<div>Color Scheme:
        <select id="scheme">
<option value="1" selected>Color Scheme 1</option>
<option value="2">Color Scheme 2</option>
<option value="3">Color Scheme 3</option>
<option value="4">Color Scheme 4</option>
<option value="5">Color Scheme 5</option>
<option value="6">Color Scheme 6</option>
        </select>
        <input type="button" value="Render" id="render_btn" onclick="render()"/>
        Scroll your mouse on the canvas to zoomin/zoomout
        </div>

        <canvas style="border:1px solid;" id="thecanvas" width="500" height="500"></canvas>
    </div>

</body>
</html>

Using Android Async Task to Perform Background Operations

Async Task is an android helper class that will allows you to run a background processes. If you are a Java programmer, may be you are familiar with thread. If you run a long task in the main thread, the current user interface will be blocked untill the task has finished. This is not a good practice. To avoid the user interface is being blocked, the long task must be perform in another thread.

Async Task Overview

In android, the only thread that can modify the user interface is called UI thread. This is means you can’t modify user interface from another thread. This is a problem, because in another side, we need to run a long task in separate thread and also we need to update the user interface to display the task progress. Actually, android provides a [cci]Handler[/cci] class that allows you to update the user interface from another thread. But we’ll discuss it in the next tutorial.

Rather than create new thread and handler, android has provides a helper class, [cci]AsyncTask[/cci], to do the same thing. The concept is same, [cci]AsyncTask[/cci] is a smart helper that encapsulates the creation of thread and handler.

[cci]AsyncTask[/cci] must be subclassed to be used. There are three methods that need to be overridden, [cci]doInbackground[/cci], [cci]onProgressUpdate[/cci] and [cci]onPostExecute[/cci]. The first method is mandatory to be overriden, the rest are optional.

[cci]doInbackground[/cci] is a method where the execution codes is placed. [cci]doProgressUpdate[/cci] and [cci]onPostExecute[/cci] run in UI thread, so user interface can be modified in both of methods. Put any codes for displaying the task progress on [cci]doProgressUpdate[/cci]. The [cci]doPostExecute[/cci] method will be called once the task has finished.

[cci]AsyncTask[/cci] is a generic class. [cci]AsyncTask[/cci] is subclassed in the form [cci]AsyncTask[/cci].

  1. [cci]Params[/cci], the type of the parameters sent to the task upon execution.
  2. [cci]Progress[/cci], the type of the progress units published during the background computation.
  3. [cci]Result[/cci], the type of the result of the background computation.

To give a better understanding, a sample application that use [cci]AsyncTask[/cci] will be given.

Creating Sample Application

We’ll create a sample application to demonstrate the use of [cci]AsyncTask[/cci] class to perform background processes. Our goal is to create a simple application which download a file from server and display the download progress in the progress bar.

Our application have very simple user interface that only contains a progress bar and a button.

AsyncTask Simple Application
AsyncTask Simple Application

If user click Start Button above, the application will start download a file from server and display the progress in progress bar. After the download process has completed, the file is saved into android root folder (/sdcard).

In this demonstration, I will use a file located on my server, http://semurjengkol.com/dl/files/CustomArrayAdapter.rar(445KB), this is an eclipse project from previous tutorial. You can also use this file or change the url as you want.

Now, open your Eclipse IDE and create new Android Application Project, then follow step by step below:

  1. Create new layout file [cci]res/layout/activity_main.xml[/cci]
    This file defines the application main layout which contain a progress bar and a button.

    <LinearLayout 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:orientation="vertical"
        android:paddingLeft="5dp"
        android:paddingRight="5dp" >
    
        <ProgressBar
            android:id="@+id/progress_bar"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:indeterminate="false"
            android:max="100"
            android:progress="0" />
    
        <Button
            android:id="@+id/start_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:text="@string/start_download" />
    
    </LinearLayout>
    

    The resource [cci]@string/start_download[/cci] we used above is defined in strings resources [cci]res/values/strings.xml[/cci]

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <string name="app_name">AsyncTaskSample</string>
        <string name="action_settings">Settings</string>
        <string name="hello_world">Hello world!</string>
        <string name="start_download">Start Download</string>
    </resources>
    
  2. Create new java class [cci]src/DownloadListener.java[/cci]
    This is a listener that will be used by [cci]AsyncTask[/cci] to communicate with activity to change the user interface.

    package com.sj.asynctask;
    
    import java.io.File;
    
    public interface DownloadListener {
        public void onDownloadComplete(File filename);
        public void onProgressUpdate(int progress);
        public void onDownloadFailure(final String msg);
    }
    
  3. Create new java class [cci]src/DownloadTask.java[/cci]
    This file extends [cci]AsyncTask[/cci] and will do the download task and call the listener to display the progress result. The [cci]doInBackground[/cci] method retrieves two string parameters:

    1. URL of the file to be downloaded
    2. The destination storage location to save the file
    package com.sj.asynctask;
    
    import java.io.BufferedInputStream;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.MalformedURLException;
    import java.net.URL;
    import java.net.URLConnection;
    
    import android.os.AsyncTask;
    import android.os.Environment;
    
    public class DownloadTask extends AsyncTask<String, Integer, Boolean> {
        /** This is our listener*/
        private final DownloadListener listener;
        /** Hold message if download failure*/
        private String msg;
        /** Save Destination */
        private File saveTo; 
        
        public DownloadTask(DownloadListener listener) {
            this.listener = listener;
        }
        
        @Override
        protected Boolean doInBackground(String... params) {
            /** Params should be array of string with length 2. 
             * 1. url
             * 2. filename destination*/
            if(params == null || params.length < 2) {
                msg = "Incomplete parameters";
                return false;
            }
            
            String sUrl = params[0];
            String filename = params[1]; 
    
            /** get root directory: /sdcard */
            File rootDir = Environment.getExternalStorageDirectory(); 
            /** create destination file*/
            saveTo = new File(rootDir, filename);
        
            try {
                /** define url*/
                URL url = new URL(sUrl);
                /** open the connection*/
                URLConnection conn = url.openConnection();
                conn.connect();
                
                /** get the size of file that will be downloaded. It will be used to measure the progress*/
                int fileLength = conn.getContentLength(); 
                
                /** create input and outpout stream*/
                InputStream is = new BufferedInputStream(url.openStream());
                OutputStream os = new FileOutputStream(saveTo);
                
                /** create buffer*/
                byte buffer[] = new byte[512];
                /** hold total of downloaded bytes*/
                long totalDownloaded = 0;
                int count;
                
                while ((count = is.read(buffer)) != -1) {
                    totalDownloaded += count;
                    
                    /**cause call to onProgressUpdate, which is run on UI thread*/
                    publishProgress((int) (totalDownloaded * 100 / fileLength));                 
                    os.write(buffer, 0, count);
                }
                
                /** closing stream*/
                os.flush();
                os.close();
                is.close();
                return true;
            } 
            catch (MalformedURLException e) {
                msg = "Invalid URL";
            }
            catch (IOException e) {
                msg = "No internet connection";
            }
            
            return false;
        }
        
        @Override
        protected void onProgressUpdate(Integer... values) {
            if(listener != null) listener.onProgressUpdate(values[0]);
        }
        
        @Override
        protected void onPostExecute(Boolean result) {
            if(!result) {
                if(listener != null) listener.onDownloadFailure(msg);
                return;
            } 
            
            if(listener != null) listener.onDownloadComplete(saveTo);
        }
    }
    

  4. Create main activity [cci]src/MainActivity.java[/cci]
    This is our main activity that will inflate the [cci]res/layout/activity_main.xml[/cci] to build our main user interface. The activity will create and execute [cci]DownloadTask[/cci] object when Start Button is clicked. Our activity also implements the [cci]DownloadListener[/cci] and set itself as a listener to [cci]DownloadTask[/cci] object. The [cci]DownloadTask[/cci] object will call the listener method implementation in the activity when the progress updated, download failure and when download completed.

    package com.sj.asynctask;
    
    import java.io.File;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.ProgressBar;
    import android.widget.Toast;
    
    public class MainActivity extends Activity implements OnClickListener, DownloadListener{
        private ProgressBar progressBar;
        private Button startButton;
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            initView();
        }
        
        private void initView() {
            progressBar = (ProgressBar) findViewById(R.id.progress_bar);
            startButton = (Button)findViewById(R.id.start_button);
            
            if(startButton != null) startButton.setOnClickListener(this);
        }
    
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
            case R.id.start_button:
                /** file url to be downloaded*/
                String url = "http://semurjengkol.com/dl/files/CustomArrayAdapter.rar";
                /** destination filename*/
                String filename = "CustomArrayAdapter.rar";
                
                if(startButton != null) startButton.setEnabled(false);
                
                DownloadTask task = new DownloadTask(this);
                task.execute(url, filename);
                break;
            default:
                break;
            }        
        }
    
        @Override
        public void onDownloadComplete(File filename) {
            if(filename != null) {
                Toast.makeText(this, "Download complete. File is saved to " + filename.getPath(), 
                        Toast.LENGTH_LONG).show();
            }
            
            if(startButton != null) startButton.setEnabled(true);
        }
    
        @Override
        public void onProgressUpdate(int progress) {
            if(progressBar != null) progressBar.setProgress(progress);
        }
    
        @Override
        public void onDownloadFailure(String msg) {
            Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
            if(progressBar != null) progressBar.setProgress(0);
            if(startButton != null) startButton.setEnabled(true);
        }
    }
    
  5. Adding permission to [cci]AndroidManifest.xml[/cci]
    This simple application has two main features:

    • Connecting to internet to download a file
    • Save the file into sdcard storage

    In order to our application runs well, we must add [cci]uses-permission[/cci] in our [cci]AndroidManifest.xml[/cci] related to above features. Add the following lines into [cci]AndroidManifest.xml[/cci]:

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

    Below is our final [cci]AndroidManifest.xml[/cci]:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.sj.asynctask"
        android:versionCode="1"
        android:versionName="1.0" >
    
        <uses-sdk
            android:minSdkVersion="8"
            android:targetSdkVersion="17" />
    
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.INTERNET" />
        
        <application
            android:allowBackup="true"
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name"
            android:theme="@style/AppTheme" >
            <activity
                android:name="com.sj.asynctask.MainActivity"
                android:label="@string/app_name" >
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
    </manifest>
    

Now run the project and click the start button, it will download the file and display the progress on the progress bar

Async Task Download Progress
Async Task Download Progress

Using Custom Array Adapter on Android List View

List View is an element that displays a collection of items in single column direction. It has an internal vertical scroll bar that enable user to scroll if it’s height bigger than display height. The type of single item in the list is any of java object.

[cci]ListView[/cci] needs an adapter to works. This adapter behaves as a data resources for the list. The adapter also defines how each items in the list is displayed. The adapter is attached to the list via [cci]setAdapter[/cci] method on the [cci]ListView[/cci] object. There are two commons used adapters:

  • Array Adapter: An adapter that is designed to work with arrays data resources.
  • Cursor Adapter: An adapter that is designed to handle database related data.

This tutorial will focuses on array adapter.

Simple Array Adapter

A simple array adapter is an array adapter that is built using array of string as items. The array of string is passed to the constructor of [cci]ArrayAdapter[/cci] object.

List<String> apps = new ArrayList<String>();
apps.add("Twitter");
apps.add("Whatsapp");
apps.add("Facebook");
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, apps);

The constructor of array adapter have 3 arguments:

  1. context: this is the application context
  2. layout resource id: the layout resource id for item view
  3. array items: this is array object for items

We will attach the created adapter into the list by using [cci]setAdapter[/cci] method on [cci]ListView[/cci] object.

List Activity

[cci]ListActivity[/cci] is a subclass of [cci]Activity[/cci] that will make our work with [cci]ListView[/cci] easier. [cci]ListActivity[/cci] has internal implementation method that is related to [cci]ListView[/cci]. You must have list view object with id is [cci]android:id/list[/cci] in the layout file to use List Activity.

<ListView
   android:id="@android:id/list"
   android:layout_width="match_parent"
   android:layout_height="wrap_content" >
</ListView>

Now we will create a sample list view application using simple array adapter. Open your Eclipse IDE and create new android project by selecting menu: File -> New -> Android Application Project. Fill out required fields.

  1. Create new xml file: [cci]activity_main.xml[/cci]
    <LinearLayout 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" >
    
        <ListView
            android:id="@android:id/list"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
        </ListView>
    
    </LinearLayout>
    
  2. Create new activity class: [cci]MainActivity.java[/cci]
    package com.sj.customlistview;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import android.app.ListActivity;
    import android.os.Bundle;
    import android.widget.ArrayAdapter;
    
    public class MainActivity extends ListActivity{    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);        
            setContentView(R.layout.activity_main);        
            initView();   
        }
    
        private void initView() {
            List<String> apps = new ArrayList<String>();
            apps.add("Twitter");
            apps.add("Whatsapp");
            apps.add("Facebook");
            ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, apps);
            setListAdapter(adapter);
        }
    }
    
  3. Put your activity in [cci]AndroidManifest.xml[/cci] file
  4. <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.sj.customlistview"
        android:versionCode="1"
        android:versionName="1.0" >
    
        <uses-sdk
            android:minSdkVersion="8"
            android:targetSdkVersion="17" />
    
        <application
            android:allowBackup="true"
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name"
            android:theme="@style/AppTheme" >
            <activity
                android:name="com.sj.customlistview.MainActivity"
                android:label="@string/app_name" >
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
    
    </manifest>
    

Run your project, your list view will be displayed like image below:

Simple Android List View
Simple Android List View


Customize Array Adapter

By default, array adapter displays a [cci]TextView[/cci] for each items and set the text of it by calling [cci]toString[/cci] method of item object. We can customize the default display of array adapter by overriding [cci]getView[/cci] method.
For a demo, we will modify previous project and use custom array adapter:

  1. Create new java class: [cci]Application.java[/cci].
    This class represents a single object of list item.

    package com.sj.customlistview;
    
    public class Application {
        private String title;
        private long totalDl;
        private int rating;
        private String icon;
        
        public String getTitle() {
            return title;
        }
        public void setTitle(String title) {
            this.title = title;
        }
        public long getTotalDl() {
            return totalDl;
        }
        public void setTotalDl(long totalDl) {
            this.totalDl = totalDl;
        }
        public int getRating() {
            return rating;
        }
        public void setRating(int rating) {
            this.rating = rating;
        }
        public String getIcon() {
            return icon;
        }
        public void setIcon(String icon) {
            this.icon = icon;
        }
    }
    
  2. Create new xml file: [cci]app_custom_list.xml[/cci]
    This file defines a view for list item

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >
    
        <ImageView
            android:id="@+id/appIcon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true"        
            android:layout_marginLeft="3dp"
            android:layout_marginTop="3dp"
            android:src="@drawable/facebook" />
        <TextView
            android:id="@+id/titleTxt"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignTop="@id/appIcon"
            android:layout_toRightOf="@id/appIcon"
            android:layout_marginLeft="3dp"
            android:text="Application Title"
            android:textSize="22dp"/>
    
        <LinearLayout
            android:id="@+id/ratingCntr"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@id/appIcon"
            android:layout_below="@id/titleTxt"
            android:layout_marginLeft="5dp" >
        </LinearLayout>
    
        <TextView
            android:id="@+id/dlTxt"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/titleTxt"
            android:layout_alignParentRight="true"
            android:layout_marginRight="3dp"
            android:text="0 dl" />    
    </RelativeLayout>
    
  3. Create new java class: [cci]AppAdapter.java[/cci]
    This is our adapter that will inflate [cci]app_custom_list.xml[/cci] and set the data into it.

    package com.sj.customlistview;
    
    import java.text.NumberFormat;
    import java.util.List;
    
    import android.content.Context;
    import android.content.res.Resources;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ArrayAdapter;
    import android.widget.ImageView;
    import android.widget.LinearLayout;
    import android.widget.TextView;
    
    public class AppAdapter extends ArrayAdapter<Application>{
        private List<Application> items;
        
        public AppAdapter(Context context, List<Application> items) {
            super(context, R.layout.app_custom_list, items);
            this.items = items;
        }
        
        @Override
        public int getCount() {
            return items.size();
        }
        
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View v = convertView;
            
            if(v == null) {
                LayoutInflater li = LayoutInflater.from(getContext());
                v = li.inflate(R.layout.app_custom_list, null);            
            }
            
            Application app = items.get(position);
            
            if(app != null) {
                ImageView icon = (ImageView)v.findViewById(R.id.appIcon);
                TextView titleText = (TextView)v.findViewById(R.id.titleTxt);
                LinearLayout ratingCntr = (LinearLayout)v.findViewById(R.id.ratingCntr);
                TextView dlText = (TextView)v.findViewById(R.id.dlTxt);
                
                if(icon != null) {
                    Resources res = getContext().getResources();
                    String sIcon = "com.sj.customlistview:drawable/" + app.getIcon();
                    icon.setImageDrawable(res.getDrawable(res.getIdentifier(sIcon, null, null)));
                }
                
                if(titleText != null) titleText.setText(app.getTitle());
                
                if(dlText != null) {
                    NumberFormat nf = NumberFormat.getNumberInstance();
                    dlText.setText(nf.format(app.getTotalDl())+" dl");            
                }
                
                if(ratingCntr != null && ratingCntr.getChildCount() == 0) {        
                    /*
                     * max rating: 5
                     */
                    for(int i=1; i<=5; i++) {
                        ImageView iv = new ImageView(getContext());
                        
                        if(i <= app.getRating()) {
                            iv.setImageDrawable(getContext().getResources().getDrawable(R.drawable.start_checked));
                        }
                        else {                
                            iv.setImageDrawable(getContext().getResources().getDrawable(R.drawable.start_unchecked));
                        }
                        
                        ratingCntr.addView(iv);
                    }
                }
            }
            
            return v;
        }
    }
    
  4. Open your [cci]MainActivity.java[/cci] and modify several lines.
    package com.sj.customlistview;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import android.app.ListActivity;
    import android.os.Bundle;
    
    public class MainActivity extends ListActivity{    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);        
            setContentView(R.layout.activity_main);        
            initView();   
        }
    
        private void initView() {
            List<Application> apps = populateSampleApplication();
            AppAdapter adapter = new AppAdapter(this, apps);
            setListAdapter(adapter);        
        }
        
        private List<Application> populateSampleApplication(){        
            String[] apps = new String[] {                
                "Twitter,450000,5,twitter",
                "Skype,300002,2,skype",
                "Facebook,500560,4,facebook"
            };
            
            List<Application> list = new ArrayList<Application>();
            
            for(String app:apps) {
                String[] rApp = app.split(","); 
                Application ap = new Application();
                ap.setTitle(rApp[0]);
                ap.setTotalDl(Integer.parseInt(rApp[1]));
                ap.setRating(Integer.parseInt(rApp[2]));
                ap.setIcon(rApp[3]);
                list.add(ap);
            }
            
            return list;
        }
    }
    

I’ve used some social icons in this project. You can download the icons here: social icons
Now run your project, it will display list view below:

Custom Array Adapter
Custom Array Adapter

Android Gravity and Layout Gravity

Gravity is an android method for aligning view in a layout. There are two kinds of gravity, gravity and layout gravity. Basically a gravity is set in xml layout files, but you can also set a gravity of any view in java source code. To set gravity in xml use [cci]android:layout_gravity[/cci] and [cci]android:gravity[/cci] attributes. The values of both attributes is combination of the following constants:

top : Push object to the top of its container, not changing its size.
bottom : Push object to the bottom of its container, not changing its size.
left : Push object to the left of its container, not changing its size.
right : Push object to the right of its container, not changing its size.
center_vertical : Place object in the vertical center of its container, not changing its size.
fill_vertical : Grow the vertical size of the object if needed so it completely fills its container.
center_horizontal : Place object in the horizontal center of its container, not changing its size.
fill_horizontal : Grow the horizontal size of the object if needed so it completely fills its container.
center : Place the object in the center of its container in both the vertical and horizontal axis, not changing its size.
fill : Grow the horizontal and vertical size of the object if needed so it completely fills its container.
clip_vertical : Additional option that can be set to have the top and/or bottom edges of the child clipped to its container’s bounds. The clip will be based on the vertical gravity: a top gravity will clip the bottom edge, a bottom gravity will clip the top edge, and neither will clip both edges.
clip_horizontal : Additional option that can be set to have the left and/or right edges of the child clipped to its container’s bounds. The clip will be based on the horizontal gravity: a left gravity will clip the right edge, a right gravity will clip the left edge, and neither will clip both edges.
start : Push object to the beginning of its container, not changing its size.
end : Push object to the end of its container, not changing its size.

android:gravity attribute

[cci]android:gravity[/cci] will set alignment to the content of a view. This aligment will only take effect if size of view is bigger than view’s content. Maybe you got confuse, what is the different between view and view content. Consider a button view below.

Button View
Button View

As you can see from image above, the button view is the rectangle boundary of a button, while the content of the button view is the text “button” it self.

Now, we will align the content of the button to bottom right of the button. To align content to bottom right we add [cci]android:gravity=”bottom|right”[/cci] attribute.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <Button
        android:id="@+id/button1"
        android:layout_width="match_parent"
        android:layout_height="70dp"
        android:text="Button"
        android:gravity="bottom|right" />

</LinearLayout>

Will result as follow:

Content of button view aligned to bottom right
Content of button view aligned to bottom right

android:layout_gravity attribute

[cci]android:layout_gravity[/cci] is used to align view child to its parent. Note that this attribute will only take effect if the parent is [cci]LinearLayout[/cci] and the size of child smaller than parent size.


Now we will align a button to the right of parent. To do this, we must add [cci]android:layout_gravity=”right”[/cci] attribute.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button"
        android:layout_gravity="right" />

</LinearLayout>

The result is as follow:

Button view is aligned to right
Button view is aligned to right