<?xml version="1.0" encoding="UTF-8" standalone="no"?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0"><channel><title>My Personal Blog</title><description>Blog Seputar Pemrograman Java, Android, iOS, Web, Database, Teknik Komputer dan Jaringan, Artikel, Agama dan Lain-lain</description><managingEditor>noreply@blogger.com (Wim Sonevel)</managingEditor><pubDate>Sun, 23 Nov 2025 08:50:50 +0700</pubDate><generator>Blogger http://www.blogger.com</generator><openSearch:totalResults xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/">215</openSearch:totalResults><openSearch:startIndex xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/">1</openSearch:startIndex><openSearch:itemsPerPage xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/">25</openSearch:itemsPerPage><link>http://wimsonevel.blogspot.com/</link><language>en-us</language><itunes:explicit>no</itunes:explicit><itunes:subtitle>Blog Seputar Pemrograman Java, Android, iOS, Web, Database, Teknik Komputer dan Jaringan, Artikel, Agama dan Lain-lain</itunes:subtitle><itunes:owner><itunes:email>noreply@blogger.com</itunes:email></itunes:owner><item><title>(Tutorial iOS) Add Load More in UITableView</title><link>http://wimsonevel.blogspot.com/2018/08/tutorial-ios-add-load-more-in.html</link><category>iOS</category><category>Swift</category><author>noreply@blogger.com (Wim Sonevel)</author><pubDate>Mon, 27 Aug 2018 11:09:00 +0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-6966757688576433754.post-5158496319299542124</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilTV9veUcfjxodZdVpwIpdHXxuKdbPl6j-c_3sp5SiD7bqXL0ilK6RvOWI4AnBq6ElrVW7KLdeXH4OCB7xJzBMAfwgbAqhtRN0c8JtGxn2gyQDj8RdeH2bodZgkMGeGdDdhyphenhyphenzztt_fH60/s1600/ios+load+more.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="800" data-original-width="1280" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilTV9veUcfjxodZdVpwIpdHXxuKdbPl6j-c_3sp5SiD7bqXL0ilK6RvOWI4AnBq6ElrVW7KLdeXH4OCB7xJzBMAfwgbAqhtRN0c8JtGxn2gyQDj8RdeH2bodZgkMGeGdDdhyphenhyphenzztt_fH60/s640/ios+load+more.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
Hello guys, pada kesempatan sebelumnya saya sudah menjelaskan tentang bagaimana membuat custom tableview di ios. Bisa dilihat di sini &lt;a href="https://wimsonevel.blogspot.com/2017/07/tutorial-ios-custom-uitableviewcell-in.html"&gt;&lt;span style="color: red;"&gt;https://wimsonevel.blogspot.com/2017/07/tutorial-ios-custom-uitableviewcell-in.html&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Tutorial kali ini saya akan akan menjelaskan bagaimana menambahkan load more di tableview atau bisa disebut &lt;b&gt;paging&lt;/b&gt;. Mekanismenya ketika kita men-drag scroll sampai ke bawah, pada saat itu lakukan request untuk memuat data.&lt;br /&gt;
&lt;br /&gt;
Oke langsung saja.&lt;br /&gt;
&lt;br /&gt;
Pertama kita perlu menambahkan sebuah View yang bernama &lt;b&gt;UIActivityIndicatorView&lt;/b&gt; dibagian footer dari &lt;b&gt;UITabelView&lt;/b&gt;. Akan muncul loading indicator ketika tableview di drag atau scroll ke bawah. Buat extension dari &lt;b&gt;UITableView&lt;/b&gt; dengan beberapa fungsi yaitu&amp;nbsp;&lt;b&gt;showLoadingFooter&lt;/b&gt;, &lt;b&gt;hideLoadingFooter&lt;/b&gt; dan &lt;b&gt;isLoadingFooterShowing&lt;/b&gt;.

&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
import Foundation&lt;br/&gt;
import UIKit&lt;br/&gt;

// MARK: Loading Footer
extension UITableView {
    
    func showLoadingFooter(){
        let loadingFooter = UIActivityIndicatorView(activityIndicatorStyle: .gray)
        loadingFooter.frame.size.height = 60
        loadingFooter.hidesWhenStopped = true
        loadingFooter.startAnimating()
        tableFooterView = loadingFooter
    }
    
    func hideLoadingFooter(){
        let tableContentSufficentlyTall = (contentSize.height &amp;gt; frame.size.height)
        let atBottomOfTable = (contentOffset.y &amp;gt;= contentSize.height - frame.size.height)
        if atBottomOfTable &amp;amp;&amp;amp; tableContentSufficentlyTall {
            UIView.animate(withDuration: 0.2, animations: {
                self.contentOffset.y = self.contentOffset.y - 60
            }, completion: { finished in
                self.tableFooterView = UIView()
            })
        } else {
            self.tableFooterView = UIView()
        }
    }
    
    func isLoadingFooterShowing() -&amp;gt; Bool {
        return tableFooterView is UIActivityIndicatorView
    }
    
}

&lt;/code&gt;
&lt;/pre&gt;
Kemudian kita perlu mengimplementasikan function &lt;b&gt;scrollViewDidEndDragging&lt;/b&gt; di &lt;b&gt;ViewController&lt;/b&gt;.
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
override func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
        if scrollView == tableView {
            if ((scrollView.contentOffset.y + scrollView.frame.size.height) &amp;gt;= scrollView.contentSize.height) {
                if !tableView.isLoadingFooterShowing() {
                    loadData()
                }
            }
        }
    }

&lt;/code&gt;
&lt;/pre&gt;
Buat method &lt;b&gt;loadData()&lt;/b&gt;, kemudian tampilkan loading indicator di tableview footer diikuti dengan reload data atau dari request data.

&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
func loadData() {
        // do network request here
        
        self.tableView.showLoadingFooter()
        
        DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
            
            self.foods.append(contentsOf: self.moreFoods)
            self.tableView.reloadData()
            
            self.tableView.hideLoadingFooter()
        }
    }
&lt;/code&gt;
&lt;/pre&gt;
Kode lengkapnya :
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
import UIKit

class ViewController: UITableViewController {

    var foods = [Food(thumb: "rendang", name: "Rendang", country: "Indonesia"),
                 Food(thumb: "nasi_goreng", name: "Nasi Goreng", country: "Indonesia"),
                 Food(thumb: "sushi", name: "Sushi", country: "Japan"),
                 Food(thumb: "tom_yum_goong", name: "Tom Yum Goong", country: "Thailand"),
                 Food(thumb: "pad_thai", name: "Pad Thai", country: "Thailand"),
                 Food(thumb: "som_tam", name: "Som Tam", country: "Thailand"),
                 Food(thumb: "dim_sum", name: "Dim Sum", country: "Hongkong"),
                 Food(thumb: "ramen", name: "Ramen", country: "Japan"),
                 Food(thumb: "peking_duck", name: "Peking Duck", country: "China"),
                 Food(thumb: "massaman_curry", name: "Massaman Curry", country: "Thailand")]
    
    var moreFoods: [Food] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        self.moreFoods.append(contentsOf: self.foods)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func loadData() {
        // do network request here
        
        self.tableView.showLoadingFooter()
        
        DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
            
            self.foods.append(contentsOf: self.moreFoods)
            self.tableView.reloadData()
            
            self.tableView.hideLoadingFooter()
        }
    }

}

struct Food {
    
    var thumb = String()
    var name = String()
    var country = String()
    
}

class CustomCell: UITableViewCell {
    
    @IBOutlet weak var thumbImageView: UIImageView!
    @IBOutlet weak var nameLabel: UILabel!
    @IBOutlet weak var countryLabel: UILabel!
    
}

extension ViewController {
    
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -&amp;gt; Int {
        return foods.count
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -&amp;gt; UITableViewCell {
        
        let food = foods[indexPath.row]
        
        let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell
        
        cell.thumbImageView.image = UIImage(named: food.thumb)
        
        cell.nameLabel?.text = food.name
        cell.countryLabel.text = food.country
        
        return cell
    }
    
    override func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
        if scrollView == tableView {
            if ((scrollView.contentOffset.y + scrollView.frame.size.height) &amp;gt;= scrollView.contentSize.height) {
                if !tableView.isLoadingFooterShowing() {
                    loadData()
                }
            }
        }
    }
}

&lt;/code&gt;
&lt;/pre&gt;
Build dan jalankan maka hasilnya seperti dibawah ini.

&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZyxZuJjQY1TfDVI30Lmaio7e07mLjF2dHOpfab8uXuYDUL1nkGbml2QAn2D4hhN8i-hafNGW5dl-UDiWzRyhDT9YKRFC6r6-UlJeHb9xJaBLfzLVu4LJEOTaAfibq23mWnIWhacx0WVs/s1600/Simulator+Screen+Shot+Aug+27%252C+2018%252C+10.38.05+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="1136" data-original-width="640" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZyxZuJjQY1TfDVI30Lmaio7e07mLjF2dHOpfab8uXuYDUL1nkGbml2QAn2D4hhN8i-hafNGW5dl-UDiWzRyhDT9YKRFC6r6-UlJeHb9xJaBLfzLVu4LJEOTaAfibq23mWnIWhacx0WVs/s400/Simulator+Screen+Shot+Aug+27%252C+2018%252C+10.38.05+AM.png" width="225" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Source lengkap dapat dilihat di&amp;nbsp;&lt;a href="https://github.com/wimsonevel/Paging-UITableView"&gt;https://github.com/wimsonevel/Paging-UITableView&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Sekian tutorial singkat kali ini.&lt;br /&gt;
Jangan lupa share ke social media kalian ^^.</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilTV9veUcfjxodZdVpwIpdHXxuKdbPl6j-c_3sp5SiD7bqXL0ilK6RvOWI4AnBq6ElrVW7KLdeXH4OCB7xJzBMAfwgbAqhtRN0c8JtGxn2gyQDj8RdeH2bodZgkMGeGdDdhyphenhyphenzztt_fH60/s72-c/ios+load+more.png" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>(Tutorial iOS) Pull to Refresh with UIRefreshControl</title><link>http://wimsonevel.blogspot.com/2018/08/tutorial-ios-pull-to-refresh-with.html</link><category>iOS</category><category>Swift</category><author>noreply@blogger.com (Wim Sonevel)</author><pubDate>Mon, 20 Aug 2018 17:30:00 +0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-6966757688576433754.post-3176272137722354730</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxp1bJmvYISgGiT5Of3h7XDnyrYKwBvNDsXiraGwLl-SNBcyodowgSBpJ24-pJTp4wT82yU3vicxB2R8IjrNu31YqKeagnRDynR7lFmw82xl11M2T8gF1a5q3Skabd_p2C96FF14qvaUA/s1600/ios+pull+to+refresh.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="800" data-original-width="1280" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxp1bJmvYISgGiT5Of3h7XDnyrYKwBvNDsXiraGwLl-SNBcyodowgSBpJ24-pJTp4wT82yU3vicxB2R8IjrNu31YqKeagnRDynR7lFmw82xl11M2T8gF1a5q3Skabd_p2C96FF14qvaUA/s640/ios+pull+to+refresh.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Hello guys, pada kesempatan sebelumnya saya sudah menjelaskan tentang bagaimana membuat custom &lt;b&gt;tableview&lt;/b&gt; di ios. Bisa dilihat di sini &lt;a href="https://wimsonevel.blogspot.com/2017/07/tutorial-ios-custom-uitableviewcell-in.html"&gt;&lt;span style="color: red;"&gt;https://wimsonevel.blogspot.com/2017/07/tutorial-ios-custom-uitableviewcell-in.html&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Tutorial kali ini pada dasarnya meneruskan tutorial yang sebelumnya yakni dengan menambahkan &lt;b&gt;Pull to Refresh&lt;/b&gt;. Untuk membuat pull to refresh di iOS dapat menggunakan widget yang dinamakan &lt;b&gt;UIRefreshControl&lt;/b&gt;. Implementasinya cukup sederhana yaitu dengan menempakannya ke dalam table view yang kita buat.
&lt;br /&gt;
&lt;br /&gt;
Oke, langsung aja ke TKP.&lt;br /&gt;
&lt;br /&gt;
Pertama, deklarasikan variabel &lt;b&gt;UIRefreshControl&lt;/b&gt; berikut.
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
let pullRefresh = UIRefreshControl()
&lt;/code&gt;
&lt;/pre&gt;
Buat function untuk menghandle refresh control. Di sini lah tempat menghandle network request. Untuk sementara saya menggunakan thread biasa.
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
func pullRefresh(_ refreshControl: UIRefreshControl) {
    // do network request here
        
    DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
        self.tableView.reloadData()
        refreshControl.endRefreshing()
    }
}
&lt;/code&gt;
&lt;/pre&gt;
Lalu atur properties-nya (warna, text, dll) sesuai keinginan.
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
// Refresh Control Properties
pullRefresh.addTarget(self, action: #selector(ViewController.pullRefresh(_:)), for: UIControlEvents.valueChanged)
        
pullRefresh.tintColor = UIColor.red
pullRefresh.attributedTitle = NSAttributedString(string: "Please wait ...")
&lt;/code&gt;
&lt;/pre&gt;
Kemudian tambakan ke dalam tableview sebagai subview.
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
// Add to Table View
if #available(iOS 10.0, *) {
    tableView.refreshControl = pullRefresh
} else {
    tableView.addSubview(pullRefresh)
}
&lt;/code&gt;
&lt;/pre&gt;
Berikut source code lengkapnya :
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;" class="language-swift"&gt;
import UIKit

class ViewController: UITableViewController {

    
    var foods = [Food(thumb: "rendang", name: "Rendang", country: "Indonesia"),
                 Food(thumb: "nasi_goreng", name: "Nasi Goreng", country: "Indonesia"),
                 Food(thumb: "sushi", name: "Sushi", country: "Japan"),
                 Food(thumb: "tom_yum_goong", name: "Tom Yum Goong", country: "Thailand"),
                 Food(thumb: "pad_thai", name: "Pad Thai", country: "Thailand"),
                 Food(thumb: "som_tam", name: "Som Tam", country: "Thailand"),
                 Food(thumb: "dim_sum", name: "Dim Sum", country: "Hongkong"),
                 Food(thumb: "ramen", name: "Ramen", country: "Japan"),
                 Food(thumb: "peking_duck", name: "Peking Duck", country: "China"),
                 Food(thumb: "massaman_curry", name: "Massaman Curry", country: "Thailand")]
    
    let pullRefresh = UIRefreshControl()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        // Refresh Control Properties
        pullRefresh.addTarget(self, action: #selector(ViewController.pullRefresh(_:)), for: UIControlEvents.valueChanged)
        
        pullRefresh.tintColor = UIColor.red
        pullRefresh.attributedTitle = NSAttributedString(string: "Please wait ...")
        
        // Add to Table View
        if #available(iOS 10.0, *) {
            tableView.refreshControl = pullRefresh
        } else {
            tableView.addSubview(pullRefresh)
        }

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func pullRefresh(_ refreshControl: UIRefreshControl) {
        // do network request here
        
        DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
            self.tableView.reloadData()
            refreshControl.endRefreshing()
        }
    }

}

struct Food {
    var thumb = String()
    var name = String()
    var country = String()
}

class CustomCell: UITableViewCell {
    
    @IBOutlet weak var thumbImageView: UIImageView!
    @IBOutlet weak var nameLabel: UILabel!
    @IBOutlet weak var countryLabel: UILabel!
    
}

extension ViewController {
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -&amp;gt; Int {
        return foods.count
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -&amp;gt; UITableViewCell {
        
        let food = foods[indexPath.row]
        
        let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell
        
        cell.thumbImageView.image = UIImage(named: food.thumb)
        
        cell.nameLabel?.text = food.name
        cell.countryLabel.text = food.country
        
        return cell
        
    }

}
&lt;/code&gt;
&lt;/pre&gt;
&lt;br /&gt;
Build dan run, maka hasilnya sebagai berikut :

&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEic4-v6Zortdx1HPNXzvewWR-E7QbOvRsSXOwNoG8Io1xYDDUVENrj_vsKLjpYprJPx4LJWaJ6V6nSbiRnFT2zStU-yswoMyRDZC_qxhl5BwKLwEW6XasDJU1SJqvfHocjyr-rzGSZEqdo/s1600/Simulator+Screen+Shot+Aug+20%252C+2018%252C+5.20.02+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="1136" data-original-width="640" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEic4-v6Zortdx1HPNXzvewWR-E7QbOvRsSXOwNoG8Io1xYDDUVENrj_vsKLjpYprJPx4LJWaJ6V6nSbiRnFT2zStU-yswoMyRDZC_qxhl5BwKLwEW6XasDJU1SJqvfHocjyr-rzGSZEqdo/s400/Simulator+Screen+Shot+Aug+20%252C+2018%252C+5.20.02+PM.png" width="225" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
&lt;span id="goog_606023843"&gt;&lt;/span&gt;&lt;span id="goog_606023844"&gt;&lt;/span&gt;&lt;br /&gt;
Source code lengkap dapat dilihat di&amp;nbsp;&lt;a href="https://github.com/wimsonevel/PullToRefresh"&gt;https://github.com/wimsonevel/PullToRefresh&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Sekian tutorial singkat kali ini, semoga bermanfaat.&lt;br /&gt;
Jangan lupa share ke social media kalian ya ^^</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxp1bJmvYISgGiT5Of3h7XDnyrYKwBvNDsXiraGwLl-SNBcyodowgSBpJ24-pJTp4wT82yU3vicxB2R8IjrNu31YqKeagnRDynR7lFmw82xl11M2T8gF1a5q3Skabd_p2C96FF14qvaUA/s72-c/ios+pull+to+refresh.png" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></item><item><title>(Tutorial Android) Android Image Slider</title><link>http://wimsonevel.blogspot.com/2018/08/tutorial-android-android-image-slider.html</link><category>Android</category><author>noreply@blogger.com (Wim Sonevel)</author><pubDate>Tue, 14 Aug 2018 14:47:00 +0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-6966757688576433754.post-6367232332585677933</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAoweZd-QpiGTPzv5UsBqxsW5YWojGos9Yz3y34WXRv_ozXfIlC41SzAU2yd2qYTun03wjGOWi43eF0sst6GkCvBtPOvIlC4SksMsalNcNFIcS5MGd0mtfMKUTQUMDqlgJzbhlPg7Agqw/s1600/android+image+slider.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="800" data-original-width="1280" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAoweZd-QpiGTPzv5UsBqxsW5YWojGos9Yz3y34WXRv_ozXfIlC41SzAU2yd2qYTun03wjGOWi43eF0sst6GkCvBtPOvIlC4SksMsalNcNFIcS5MGd0mtfMKUTQUMDqlgJzbhlPg7Agqw/s640/android+image+slider.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Hai guys, sudah sekian lama rasanya ane gak nulis di blog ini (kira2 setahun). Maklum guys karena ane belakangan ini sibuk banget jadi gak sempat bikin tutorial lagi, ditambah lagi juga malas yang berkepanjangan.. :v
&lt;br /&gt;
&lt;br /&gt;
Oke2, kali ini ane mau membahas bagaimana membuat Image Slider di Android. Temen2 pasti sudah tidak asing lagi dengan yang namanya Image Slider. Jadi, Image Slider merupakan tampilan seperti slide gambar yang bisa di geser satu-persatu utk menampilkannya.&lt;br /&gt;
&lt;br /&gt;
Di Android terdapat fitur ViewPager yang bisa kita manfaatkan untuk membuat slider.&lt;br /&gt;
&lt;br /&gt;
Langsung saja ke TKP.&lt;br /&gt;
&lt;br /&gt;
Konfigurasi gradle dulu dengan menambahkan library Picasso.&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
…
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.0.1'
    compile 'com.squareup.picasso:picasso:2.5.2'
    testCompile 'junit:junit:4.12'
}
&lt;/code&gt;
&lt;/pre&gt;
&lt;br /&gt;
Buat kelas dengan nama &lt;b&gt;CirclePageIndicator&lt;/b&gt;. Kelas ini merupakan custom view untuk menampilkan indicator slider.&lt;br /&gt;
&lt;br /&gt;
Code ini pada dasarnya saya ambil dari &lt;a href="https://github.com/JakeWharton/ViewPagerIndicator/blob/master/library/src/com/viewpagerindicator/CirclePageIndicator.java"&gt;https://github.com/JakeWharton/ViewPagerIndicator/blob/master/library/src/com/viewpagerindicator/CirclePageIndicator.java&lt;/a&gt;


&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.v4.view.MotionEventCompat;
import android.support.v4.view.ViewConfigurationCompat;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;


import id.co.blogspot.wimsonevel.android_imageslider.R;

import static android.graphics.Paint.ANTI_ALIAS_FLAG;
import static android.widget.LinearLayout.HORIZONTAL;
import static android.widget.LinearLayout.VERTICAL;

/*
 * Copyright (C) 2011 Patrik Akerfeldt
 * Copyright (C) 2011 Jake Wharton
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

public class CirclePageIndicator extends View implements PageIndicator {

    private static final int INVALID_POINTER = -1;

    private float mRadius;
    private final Paint mPaintPageFill = new Paint(ANTI_ALIAS_FLAG);
    private final Paint mPaintStroke = new Paint(ANTI_ALIAS_FLAG);
    private final Paint mPaintFill = new Paint(ANTI_ALIAS_FLAG);
    private ViewPager mViewPager;
    private ViewPager.OnPageChangeListener mListener;
    private int mCurrentPage;
    private int mSnapPage;
    private float mPageOffset;
    private int mScrollState;
    private int mOrientation;
    private boolean mCentered;
    private boolean mSnap;

    private int mTouchSlop;
    private float mLastMotionX = -1;
    private int mActivePointerId = INVALID_POINTER;
    private boolean mIsDragging;


    public CirclePageIndicator(Context context) {
        this(context, null);
    }

    public CirclePageIndicator(Context context, AttributeSet attrs) {
        this(context, attrs, R.attr.vpiCirclePageIndicatorStyle);
    }

    public CirclePageIndicator(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        if (isInEditMode()) return;

        //Load defaults from resources
        final Resources res = getResources();
        final int defaultPageColor = res.getColor(R.color.default_circle_indicator_page_color);
        final int defaultFillColor = res.getColor(R.color.default_circle_indicator_fill_color);
        final int defaultOrientation = res.getInteger(R.integer.default_circle_indicator_orientation);
        final int defaultStrokeColor = res.getColor(R.color.default_circle_indicator_stroke_color);
        final float defaultStrokeWidth = res.getDimension(R.dimen.default_circle_indicator_stroke_width);
        final float defaultRadius = res.getDimension(R.dimen.viewpager_circleindicator_radius);
        final boolean defaultCentered = res.getBoolean(R.bool.default_circle_indicator_centered);
        final boolean defaultSnap = res.getBoolean(R.bool.default_circle_indicator_snap);

        //Retrieve styles attributes
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CirclePageIndicator, defStyle, 0);

        mCentered = a.getBoolean(R.styleable.CirclePageIndicator_centered, defaultCentered);
        mOrientation = a.getInt(R.styleable.CirclePageIndicator_android_orientation, defaultOrientation);
        mPaintPageFill.setStyle(Paint.Style.FILL);
        mPaintPageFill.setColor(a.getColor(R.styleable.CirclePageIndicator_pageColor, defaultPageColor));
        mPaintStroke.setStyle(Paint.Style.STROKE);
        mPaintStroke.setColor(a.getColor(R.styleable.CirclePageIndicator_strokeColor, defaultStrokeColor));
        mPaintStroke.setStrokeWidth(a.getDimension(R.styleable.CirclePageIndicator_strokeWidth, defaultStrokeWidth));
        mPaintFill.setStyle(Paint.Style.FILL);
        mPaintFill.setColor(a.getColor(R.styleable.CirclePageIndicator_fillColor, defaultFillColor));
        mRadius = a.getDimension(R.styleable.CirclePageIndicator_radius, defaultRadius);
        mSnap = a.getBoolean(R.styleable.CirclePageIndicator_snap, defaultSnap);

        Drawable background = a.getDrawable(R.styleable.CirclePageIndicator_android_background);
        if (background != null) {
            setBackgroundDrawable(background);
        }

        a.recycle();

        final ViewConfiguration configuration = ViewConfiguration.get(context);
        mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration);
    }


    public void setCentered(boolean centered) {
        mCentered = centered;
        invalidate();
    }

    public boolean isCentered() {
        return mCentered;
    }

    public void setPageColor(int pageColor) {
        mPaintPageFill.setColor(pageColor);
        invalidate();
    }

    public int getPageColor() {
        return mPaintPageFill.getColor();
    }

    public void setFillColor(int fillColor) {
        mPaintFill.setColor(fillColor);
        invalidate();
    }

    public int getFillColor() {
        return mPaintFill.getColor();
    }

    public void setOrientation(int orientation) {
        switch (orientation) {
            case HORIZONTAL:
            case VERTICAL:
                mOrientation = orientation;
                requestLayout();
                break;

            default:
                throw new IllegalArgumentException("Orientation must be either HORIZONTAL or VERTICAL.");
        }
    }

    public int getOrientation() {
        return mOrientation;
    }

    public void setStrokeColor(int strokeColor) {
        mPaintStroke.setColor(strokeColor);
        invalidate();
    }

    public int getStrokeColor() {
        return mPaintStroke.getColor();
    }

    public void setStrokeWidth(float strokeWidth) {
        mPaintStroke.setStrokeWidth(strokeWidth);
        invalidate();
    }

    public float getStrokeWidth() {
        return mPaintStroke.getStrokeWidth();
    }

    public void setRadius(float radius) {
        mRadius = radius;
        invalidate();
    }

    public float getRadius() {
        return mRadius;
    }

    public void setSnap(boolean snap) {
        mSnap = snap;
        invalidate();
    }

    public boolean isSnap() {
        return mSnap;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (mViewPager == null) {
            return;
        }
        final int count = mViewPager.getAdapter().getCount();
        if (count == 0) {
            return;
        }

        if (mCurrentPage &amp;gt;= count) {
            setCurrentItem(count - 1);
            return;
        }

        int longSize;
        int longPaddingBefore;
        int longPaddingAfter;
        int shortPaddingBefore;
        if (mOrientation == HORIZONTAL) {
            longSize = getWidth();
            longPaddingBefore = getPaddingLeft();
            longPaddingAfter = getPaddingRight();
            shortPaddingBefore = getPaddingTop();
        } else {
            longSize = getHeight();
            longPaddingBefore = getPaddingTop();
            longPaddingAfter = getPaddingBottom();
            shortPaddingBefore = getPaddingLeft();
        }

        final float threeRadius = mRadius * 3;
        final float shortOffset = shortPaddingBefore + mRadius;
        float longOffset = longPaddingBefore + mRadius;
        if (mCentered) {
            longOffset += ((longSize - longPaddingBefore - longPaddingAfter) / 2.0f) - ((count * threeRadius) / 2.0f);
        }

        float dX;
        float dY;

        float pageFillRadius = mRadius;
        if (mPaintStroke.getStrokeWidth() &amp;gt; 0) {
            pageFillRadius -= mPaintStroke.getStrokeWidth() / 2.0f;
        }

        //Draw stroked circles
        for (int iLoop = 0; iLoop &amp;lt; count; iLoop++) {
            float drawLong = longOffset + (iLoop * threeRadius);
            if (mOrientation == HORIZONTAL) {
                dX = drawLong;
                dY = shortOffset;
            } else {
                dX = shortOffset;
                dY = drawLong;
            }
            // Only paint fill if not completely transparent
            if (mPaintPageFill.getAlpha() &amp;gt; 0) {
                canvas.drawCircle(dX, dY, pageFillRadius, mPaintPageFill);
            }

            // Only paint stroke if a stroke width was non-zero
            if (pageFillRadius != mRadius) {
                canvas.drawCircle(dX, dY, mRadius, mPaintStroke);
            }
        }

        //Draw the filled circle according to the current scroll
        float cx = (mSnap ? mSnapPage : mCurrentPage) * threeRadius;
        if (!mSnap) {
            cx += mPageOffset * threeRadius;
        }
        if (mOrientation == HORIZONTAL) {
            dX = longOffset + cx;
            dY = shortOffset;
        } else {
            dX = shortOffset;
            dY = longOffset + cx;
        }
        canvas.drawCircle(dX, dY, mRadius, mPaintFill);
    }

    public boolean onTouchEvent(MotionEvent ev) {
        if (super.onTouchEvent(ev)) {
            return true;
        }
        if ((mViewPager == null) || (mViewPager.getAdapter().getCount() == 0)) {
            return false;
        }

        final int action = ev.getAction() &amp;amp; MotionEventCompat.ACTION_MASK;
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
                mLastMotionX = ev.getX();
                break;

            case MotionEvent.ACTION_MOVE: {
                final int activePointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId);
                final float x = MotionEventCompat.getX(ev, activePointerIndex);
                final float deltaX = x - mLastMotionX;

                if (!mIsDragging) {
                    if (Math.abs(deltaX) &amp;gt; mTouchSlop) {
                        mIsDragging = true;
                    }
                }

                if (mIsDragging) {
                    mLastMotionX = x;
                    if (mViewPager.isFakeDragging() || mViewPager.beginFakeDrag()) {
                        mViewPager.fakeDragBy(deltaX);
                    }
                }

                break;
            }

            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                if (!mIsDragging) {
                    final int count = mViewPager.getAdapter().getCount();
                    final int width = getWidth();
                    final float halfWidth = width / 2f;
                    final float sixthWidth = width / 6f;

                    if ((mCurrentPage &amp;gt; 0) &amp;amp;&amp;amp; (ev.getX() &amp;lt; halfWidth - sixthWidth)) {
                        if (action != MotionEvent.ACTION_CANCEL) {
                            mViewPager.setCurrentItem(mCurrentPage - 1);
                        }
                        return true;
                    } else if ((mCurrentPage &amp;lt; count - 1) &amp;amp;&amp;amp; (ev.getX() &amp;gt; halfWidth + sixthWidth)) {
                        if (action != MotionEvent.ACTION_CANCEL) {
                            mViewPager.setCurrentItem(mCurrentPage + 1);
                        }
                        return true;
                    }
                }

                mIsDragging = false;
                mActivePointerId = INVALID_POINTER;
                if (mViewPager.isFakeDragging()) mViewPager.endFakeDrag();
                break;

            case MotionEventCompat.ACTION_POINTER_DOWN: {
                final int index = MotionEventCompat.getActionIndex(ev);
                mLastMotionX = MotionEventCompat.getX(ev, index);
                mActivePointerId = MotionEventCompat.getPointerId(ev, index);
                break;
            }

            case MotionEventCompat.ACTION_POINTER_UP:
                final int pointerIndex = MotionEventCompat.getActionIndex(ev);
                final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);
                if (pointerId == mActivePointerId) {
                    final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
                    mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex);
                }
                mLastMotionX = MotionEventCompat.getX(ev, MotionEventCompat.findPointerIndex(ev, mActivePointerId));
                break;
        }

        return true;
    }

    @Override
    public void setViewPager(ViewPager view) {
        if (mViewPager == view) {
            return;
        }
        if (mViewPager != null) {
            mViewPager.setOnPageChangeListener(null);
        }
        if (view.getAdapter() == null) {
            throw new IllegalStateException("ViewPager does not have adapter instance.");
        }
        mViewPager = view;
        mViewPager.setOnPageChangeListener(this);
        invalidate();
    }

    @Override
    public void setViewPager(ViewPager view, int initialPosition) {
        setViewPager(view);
        setCurrentItem(initialPosition);
    }

    @Override
    public void setCurrentItem(int item) {
        if (mViewPager == null) {
            throw new IllegalStateException("ViewPager has not been bound.");
        }
        mViewPager.setCurrentItem(item);
        mCurrentPage = item;
        invalidate();
    }

    @Override
    public void notifyDataSetChanged() {
        invalidate();
    }

    @Override
    public void onPageScrollStateChanged(int state) {
        mScrollState = state;

        if (mListener != null) {
            mListener.onPageScrollStateChanged(state);
        }
    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        mCurrentPage = position;
        mPageOffset = positionOffset;
        invalidate();

        if (mListener != null) {
            mListener.onPageScrolled(position, positionOffset, positionOffsetPixels);
        }
    }

    @Override
    public void onPageSelected(int position) {
        if (mSnap || mScrollState == ViewPager.SCROLL_STATE_IDLE) {
            mCurrentPage = position;
            mSnapPage = position;
            invalidate();
        }

        if (mListener != null) {
            mListener.onPageSelected(position);
        }
    }

    @Override
    public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) {
        mListener = listener;
    }

    /*
     * (non-Javadoc)
     *
     * @see android.view.View#onMeasure(int, int)
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (mOrientation == HORIZONTAL) {
            setMeasuredDimension(measureLong(widthMeasureSpec), measureShort(heightMeasureSpec));
        } else {
            setMeasuredDimension(measureShort(widthMeasureSpec), measureLong(heightMeasureSpec));
        }
    }

    /**
     * Determines the width of this view
     *
     * @param measureSpec
     *            A measureSpec packed into an int
     * @return The width of the view, honoring constraints from measureSpec
     */
    private int measureLong(int measureSpec) {
        int result;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        if ((specMode == MeasureSpec.EXACTLY) || (mViewPager == null)) {
            //We were told how big to be
            result = specSize;
        } else {
            //Calculate the width according the views count
            final int count = mViewPager.getAdapter().getCount();
            result = (int)(getPaddingLeft() + getPaddingRight()
                    + (count * 2 * mRadius) + (count - 1) * mRadius + 1);
            //Respect AT_MOST value if that was what is called for by measureSpec
            if (specMode == MeasureSpec.AT_MOST) {
                result = Math.min(result, specSize);
            }
        }
        return result;
    }

    /**
     * Determines the height of this view
     *
     * @param measureSpec
     *            A measureSpec packed into an int
     * @return The height of the view, honoring constraints from measureSpec
     */
    private int measureShort(int measureSpec) {
        int result;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        if (specMode == MeasureSpec.EXACTLY) {
            //We were told how big to be
            result = specSize;
        } else {
            //Measure the height
            result = (int)(2 * mRadius + getPaddingTop() + getPaddingBottom() + 1);
            //Respect AT_MOST value if that was what is called for by measureSpec
            if (specMode == MeasureSpec.AT_MOST) {
                result = Math.min(result, specSize);
            }
        }
        return result;
    }

    @Override
    public void onRestoreInstanceState(Parcelable state) {
        SavedState savedState = (SavedState)state;
        super.onRestoreInstanceState(savedState.getSuperState());
        mCurrentPage = savedState.currentPage;
        mSnapPage = savedState.currentPage;
        requestLayout();
    }

    @Override
    public Parcelable onSaveInstanceState() {
        Parcelable superState = super.onSaveInstanceState();
        SavedState savedState = new SavedState(superState);
        savedState.currentPage = mCurrentPage;
        return savedState;
    }

    static class SavedState extends BaseSavedState {
        int currentPage;

        public SavedState(Parcelable superState) {
            super(superState);
        }

        private SavedState(Parcel in) {
            super(in);
            currentPage = in.readInt();
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            super.writeToParcel(dest, flags);
            dest.writeInt(currentPage);
        }

        @SuppressWarnings("UnusedDeclaration")
        public static final Creator&amp;lt;SavedState&amp;gt; CREATOR = new Creator&amp;lt;SavedState&amp;gt;() {
            @Override
            public SavedState createFromParcel(Parcel in) {
                return new SavedState(in);
            }

            @Override
            public SavedState[] newArray(int size) {
                return new SavedState[size];
            }
        };
    }
}

&lt;/code&gt;
&lt;/pre&gt;
Kemudian buat interface dengan nama &lt;b&gt;PageIndicator&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
Code nya juga saya ambil dari sini&amp;nbsp;&lt;a href="https://github.com/JakeWharton/ViewPagerIndicator/blob/master/library/src/com/viewpagerindicator/PageIndicator.java"&gt;https://github.com/JakeWharton/ViewPagerIndicator/blob/master/library/src/com/viewpagerindicator/PageIndicator.java&lt;/a&gt;

&lt;br /&gt;

&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
/*
 * Copyright (C) 2011 Patrik Akerfeldt
 * Copyright (C) 2011 Jake Wharton
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import android.support.v4.view.ViewPager;

/**
 * A PageIndicator is responsible to show an visual indicator on the total views
 * number and the current visible view.
 */

public interface PageIndicator extends ViewPager.OnPageChangeListener {

    /**
     * Bind the indicator to a ViewPager.
     *
     * @param view
     */
    void setViewPager(ViewPager view);

    /**
     * Bind the indicator to a ViewPager.
     *
     * @param view
     * @param initialPosition
     */
    void setViewPager(ViewPager view, int initialPosition);

    /**
     * &amp;lt;p&amp;gt;Set the current page of both the ViewPager and indicator.&amp;lt;/p&amp;gt;
     *
     * &amp;lt;p&amp;gt;This &amp;lt;strong&amp;gt;must&amp;lt;/strong&amp;gt; be used if you need to set the page before
     * the views are drawn on screen (e.g., default start page).&amp;lt;/p&amp;gt;
     *
     * @param item
     */
    void setCurrentItem(int item);

    /**
     * Set a page change listener which will receive forwarded events.
     *
     * @param listener
     */
    void setOnPageChangeListener(ViewPager.OnPageChangeListener listener);

    /**
     * Notify the indicator that the fragment list has changed.
     */
    void notifyDataSetChanged();

}

&lt;/code&gt;
&lt;/pre&gt;
Selanjutnya buat beberapa layout berikut :&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;list_item_pager.xml&lt;/b&gt;&lt;br /&gt;
Layout ini berisi ImageView untuk menampilkan image.
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"&amp;gt;

    &amp;lt;ImageView
        android:id="@+id/iv_header"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop" /&amp;gt;

&amp;lt;/RelativeLayout&amp;gt;
&lt;/code&gt;
&lt;/pre&gt;
&lt;b&gt;viewpager_slide.xml&lt;/b&gt;&lt;br /&gt;
Layout berisi ViewPager dan Custom CirclePageIndicator.
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="250dp"&amp;gt;

    &amp;lt;android.support.v4.view.ViewPager
        android:id="@+id/pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@null" /&amp;gt;

    &amp;lt;id.co.blogspot.wimsonevel.android_imageslider.widget.CirclePageIndicator
        android:id="@+id/indicator"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:padding="10dp" /&amp;gt;

&amp;lt;/RelativeLayout&amp;gt;
&lt;/code&gt;
&lt;/pre&gt;
activity_main.xml

&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="id.co.blogspot.wimsonevel.android_imageslider.MainActivity"&amp;gt;

    &amp;lt;include
        layout="@layout/viewpager_slide" /&amp;gt;

&amp;lt;/RelativeLayout&amp;gt;
&lt;/code&gt;
&lt;/pre&gt;
Tambahkan beberapa resource values yang diperlukan.&lt;br /&gt;
&lt;br /&gt;
attrs.xml
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;resources&amp;gt;

    &amp;lt;attr name="centered" format="boolean" /&amp;gt;
    &amp;lt;attr name="selectedColor" format="color" /&amp;gt;
    &amp;lt;attr name="strokeWidth" format="dimension" /&amp;gt;
    &amp;lt;attr name="unselectedColor" format="color" /&amp;gt;

    &amp;lt;!-- Circle Page Indicator --&amp;gt;
    &amp;lt;declare-styleable name="ViewPagerIndicator"&amp;gt;
        &amp;lt;!-- Style of the circle indicator. --&amp;gt;
        &amp;lt;attr name="vpiCirclePageIndicatorStyle" format="reference"/&amp;gt;
        &amp;lt;!-- Style of the icon indicator's views. --&amp;gt;
        &amp;lt;attr name="vpiIconPageIndicatorStyle" format="reference"/&amp;gt;
        &amp;lt;!-- Style of the line indicator. --&amp;gt;
        &amp;lt;attr name="vpiLinePageIndicatorStyle" format="reference"/&amp;gt;
        &amp;lt;!-- Style of the title indicator. --&amp;gt;
        &amp;lt;attr name="vpiTitlePageIndicatorStyle" format="reference"/&amp;gt;
        &amp;lt;!-- Style of the tab indicator's tabs. --&amp;gt;
        &amp;lt;attr name="vpiTabPageIndicatorStyle" format="reference"/&amp;gt;
        &amp;lt;!-- Style of the underline indicator. --&amp;gt;
        &amp;lt;attr name="vpiUnderlinePageIndicatorStyle" format="reference"/&amp;gt;
    &amp;lt;/declare-styleable&amp;gt;

    &amp;lt;declare-styleable name="CirclePageIndicator"&amp;gt;
        &amp;lt;!-- Whether or not the indicators should be centered. --&amp;gt;
        &amp;lt;attr name="centered" /&amp;gt;
        &amp;lt;!-- Color of the filled circle that represents the current page. --&amp;gt;
        &amp;lt;attr name="fillColor" format="color" /&amp;gt;
        &amp;lt;!-- Color of the filled circles that represents pages. --&amp;gt;
        &amp;lt;attr name="pageColor" format="color" /&amp;gt;
        &amp;lt;!-- Orientation of the indicator. --&amp;gt;
        &amp;lt;attr name="android:orientation"/&amp;gt;
        &amp;lt;!-- Radius of the circles. This is also the spacing between circles. --&amp;gt;
        &amp;lt;attr name="radius" format="dimension" /&amp;gt;
        &amp;lt;!-- Whether or not the selected indicator snaps to the circles. --&amp;gt;
        &amp;lt;attr name="snap" format="boolean" /&amp;gt;
        &amp;lt;!-- Color of the open circles. --&amp;gt;
        &amp;lt;attr name="strokeColor" format="color" /&amp;gt;
        &amp;lt;!-- Width of the stroke used to draw the circles. --&amp;gt;
        &amp;lt;attr name="strokeWidth" /&amp;gt;
        &amp;lt;!-- View background --&amp;gt;
        &amp;lt;attr name="android:background"/&amp;gt;
    &amp;lt;/declare-styleable&amp;gt;


&amp;lt;/resources&amp;gt;
&lt;/code&gt;
&lt;/pre&gt;
&lt;b&gt;bools.xml
&lt;/b&gt;&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;resources&amp;gt;
    &amp;lt;bool name="default_circle_indicator_centered"&amp;gt;true&amp;lt;/bool&amp;gt;
    &amp;lt;bool name="default_circle_indicator_snap"&amp;gt;false&amp;lt;/bool&amp;gt;
&amp;lt;/resources&amp;gt;
&lt;/code&gt;
&lt;/pre&gt;
&lt;b&gt;colors.xml
&lt;/b&gt;&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;resources&amp;gt;
    &amp;lt;color name="colorPrimary"&amp;gt;#5d4037&amp;lt;/color&amp;gt;
    &amp;lt;color name="colorPrimaryDark"&amp;gt;#321911&amp;lt;/color&amp;gt;
    &amp;lt;color name="colorAccent"&amp;gt;#FF4081&amp;lt;/color&amp;gt;
    &amp;lt;color name="colorWhite"&amp;gt;#FFFFFF&amp;lt;/color&amp;gt;

    &amp;lt;!-- Circle Page Indicator --&amp;gt;
    &amp;lt;color name="default_circle_indicator_fill_color"&amp;gt;@color/colorPrimary&amp;lt;/color&amp;gt;
    &amp;lt;color name="default_circle_indicator_page_color"&amp;gt;@color/colorWhite&amp;lt;/color&amp;gt;
    &amp;lt;color name="default_circle_indicator_stroke_color"&amp;gt;@android:color/transparent&amp;lt;/color&amp;gt;

&amp;lt;/resources&amp;gt;
&lt;/code&gt;
&lt;/pre&gt;
&lt;b&gt;integers.xml

&lt;/b&gt;&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;resources&amp;gt;

    &amp;lt;!-- Circle Page Indicator --&amp;gt;
    &amp;lt;integer name="default_circle_indicator_orientation"&amp;gt;0&amp;lt;/integer&amp;gt;

&amp;lt;/resources&amp;gt;
&lt;/code&gt;
&lt;/pre&gt;
Kembali ke kelas java, buat kelas dengan nama &lt;b&gt;ImagePagerAdapter&lt;/b&gt;.
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
import android.content.Context;
import android.support.v4.view.PagerAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;

import com.squareup.picasso.Picasso;

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

/**
 * Created by kwikkunusantara on 8/10/18.
 */

public class ImagePagerAdapter extends PagerAdapter {

    private Context context;
    private List&amp;lt;String&amp;gt; images;

    public ImagePagerAdapter(Context context) {
        this.context = context;
        this.images = new ArrayList&amp;lt;&amp;gt;();
    }

    public void setImages(List&amp;lt;String&amp;gt; images) {
        for (int i = 0; i &amp;lt; images.size(); i++){
            this.images.add(images.get(i));
        }
        notifyDataSetChanged();
    }

    @Override
    public int getCount() {
        return images.size();
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        String image = images.get(position);
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        View itemView = inflater.inflate(R.layout.item_image_pager, container, false);
        ImageView ivHeader = (ImageView) itemView.findViewById(R.id.iv_header);

        Picasso.with(context)
                .load(image)
                .into(ivHeader);

        container.addView(itemView);

        return itemView;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView((RelativeLayout) object);
    }
}

&lt;/code&gt;
&lt;/pre&gt;
Setelah itu tambahkan code berikut di &lt;b&gt;MainActivity&lt;/b&gt;.&amp;nbsp;
&lt;br /&gt;
&lt;br /&gt;
Di sini saya menambahkan Timer supaya Slider-nya bisa bergerak otomatis. Beberapa image saya ambil dari link Facebook nya Aliga&amp;nbsp;&amp;lt;3. *Dasar Jones&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import id.co.blogspot.wimsonevel.android_imageslider.widget.CirclePageIndicator;

public class MainActivity extends AppCompatActivity {

    private ViewPager viewPager;
    private CirclePageIndicator pagerIndicator;

    private ImagePagerAdapter imagePagerAdapter;

    private Timer timer;

    private List&amp;lt;String&amp;gt; images;

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

        viewPager = (ViewPager) findViewById(R.id.pager);
        pagerIndicator = (CirclePageIndicator) findViewById(R.id.indicator);

        imagePagerAdapter = new ImagePagerAdapter(this);

        viewPager.setAdapter(imagePagerAdapter);
        pagerIndicator.setViewPager(viewPager);

        images = new ArrayList&amp;lt;&amp;gt;();
        images.add("https://scontent.fcgk12-1.fna.fbcdn.net/v/t1.0-9/30260981_1697358283684452_5345280777774956544_n.jpg?_nc_cat=0&amp;amp;oh=780b2eba44f38c3400b8e219060b3278&amp;amp;oe=5C08A56E");
        images.add("https://scontent.fcgk12-1.fna.fbcdn.net/v/t1.0-9/30412288_1697358530351094_6652467221207449600_n.jpg?_nc_cat=0&amp;amp;oh=9c39ae9327064d3c21490a556acf28a3&amp;amp;oe=5C137E2E");
        images.add("https://scontent.fcgk12-1.fna.fbcdn.net/v/t1.0-9/30412267_1697358943684386_6572812530102566912_n.jpg?_nc_cat=0&amp;amp;oh=1876343af22cad2f49d352343eb3eb6b&amp;amp;oe=5C12B116");
        images.add("https://scontent.fcgk12-1.fna.fbcdn.net/v/t1.0-9/30261069_1697359000351047_8720462127048949760_n.jpg?_nc_cat=0&amp;amp;oh=44a1c82bebff0f61b811ef2bb94b3196&amp;amp;oe=5BC978E2");

        imagePagerAdapter.setImages(images);

        timer = new Timer();
        timer.scheduleAtFixedRate(new SliderTimer(), 3000, 5000);
    }

    private class SliderTimer extends TimerTask {

        @Override
        public void run() {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if (viewPager.getCurrentItem() &amp;lt; imagePagerAdapter.getCount() - 1) {
                        viewPager.setCurrentItem(viewPager.getCurrentItem() + 1);
                    } else {
                        viewPager.setCurrentItem(0);
                    }
                }
            });
        };
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        timer.cancel();
    }
}
&lt;/code&gt;
&lt;/pre&gt;
Terakhir tambahkan permission INTERNET di &lt;b&gt;AndroidManifest&lt;/b&gt;.
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="id.co.blogspot.wimsonevel.android_imageslider"&amp;gt;

    &amp;lt;uses-permission android:name="android.permission.INTERNET" /&amp;gt;

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

                &amp;lt;category android:name="android.intent.category.LAUNCHER" /&amp;gt;
            &amp;lt;/intent-filter&amp;gt;
        &amp;lt;/activity&amp;gt;
    &amp;lt;/application&amp;gt;

&amp;lt;/manifest&amp;gt;
&lt;/code&gt;
&lt;/pre&gt;
Build dan jalankan maka hasinya sebagai berikut :&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9zBoOhaPIbGaGVN_Oh3an0lz05i9XXQIKPs4vMJxQ6tZ-Sq2eQAxr6RWzr0V4xey_1EH9RvgFXWHO1Xt1ImUWMOThZT1A9A1OMYAXopvTS8Vz_PkbUHbS1VPU4H-D3p8SBE0hpY4K0vk/s1600/Screenshot_1534230157.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="1600" data-original-width="900" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9zBoOhaPIbGaGVN_Oh3an0lz05i9XXQIKPs4vMJxQ6tZ-Sq2eQAxr6RWzr0V4xey_1EH9RvgFXWHO1Xt1ImUWMOThZT1A9A1OMYAXopvTS8Vz_PkbUHbS1VPU4H-D3p8SBE0hpY4K0vk/s400/Screenshot_1534230157.png" width="225" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Source code lengkap dapat dilihat di&amp;nbsp;&lt;a href="https://github.com/wimsonevel/Android-ImageSlider"&gt;https://github.com/wimsonevel/Android-ImageSlider&lt;/a&gt;&lt;br /&gt;
Sekian dulu untuk tutorial kali ini dan semoga bermanfaat.&lt;br /&gt;
&lt;br /&gt;
Jangan lupa share ^^</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAoweZd-QpiGTPzv5UsBqxsW5YWojGos9Yz3y34WXRv_ozXfIlC41SzAU2yd2qYTun03wjGOWi43eF0sst6GkCvBtPOvIlC4SksMsalNcNFIcS5MGd0mtfMKUTQUMDqlgJzbhlPg7Agqw/s72-c/android+image+slider.png" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></item><item><title>(Tutorial Android) Countdown Timer with Circular Progress Animation</title><link>http://wimsonevel.blogspot.com/2017/08/tutorial-android-countdown-timer-with.html</link><category>Android</category><author>noreply@blogger.com (Wim Sonevel)</author><pubDate>Thu, 10 Aug 2017 17:22:00 +0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-6966757688576433754.post-3313022049319199248</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHGejdwRyUsycu7gu8Gir1s3wEOXUo2NizwCmcfaPUgwRTS_ap-G_WiY4t499S7paEgknR7cIoi8We-9xthZTbP8xvgFUj4HmA4nO-PjYIGeoD0DR9u2TYaFYXfEOfFXTk8kLBu5a_FXw/s1600/android+countdown.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="800" data-original-width="1280" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHGejdwRyUsycu7gu8Gir1s3wEOXUo2NizwCmcfaPUgwRTS_ap-G_WiY4t499S7paEgknR7cIoi8We-9xthZTbP8xvgFUj4HmA4nO-PjYIGeoD0DR9u2TYaFYXfEOfFXTk8kLBu5a_FXw/s640/android+countdown.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;b&gt;Countdown&lt;/b&gt; merupakan istilah dari bahasa inggris yang artinya hitung mundur. Android menyediakan kelas yang berfungsi untuk menghitung mundur yang dinamakan &lt;b&gt;CountDownTimer&lt;/b&gt;. Untuk membuat program countdown, kita tinggal mengimplementasikan kelas tersebut. Pada kesempatan kali ini saya akan membagikan sedikit tutorial hasil dari request teman-teman. Kita akan membuat program countdown dengan animasi circular progress.&lt;br /&gt;
&lt;br /&gt;
Oke langsung saja kita ke TKP.&lt;br /&gt;
&lt;br /&gt;
Pertama, buat &lt;b&gt;project baru&lt;/b&gt; (wajib hehehe). &lt;br /&gt;
&lt;br /&gt;
Selanjutnya kita membuat &lt;b&gt;circular progress&lt;/b&gt;. Di sini kita harus membuat &lt;b&gt;custom view&lt;/b&gt; sendiri untuk membuat circular progress, karena di Android sendiri memang tidak disediakan. Berikut adalah codenya saya ambil dan modifikasi sedikit dari &lt;a href="https://github.com/lzyzsd/CircleProgress"&gt;https://github.com/lzyzsd/CircleProgress&lt;/a&gt;. Beri nama &lt;b&gt;DonutProgress.java&lt;/b&gt; :
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Bundle;
import android.os.Parcelable;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by bruce on 11/4/14.
 */

public class DonutProgress extends View {

    private Paint finishedPaint;
    private Paint unfinishedPaint;
    private Paint innerCirclePaint;

    protected Paint textPaint;
    protected Paint innerBottomTextPaint;

    private RectF finishedOuterRect = new RectF();
    private RectF unfinishedOuterRect = new RectF();

    private int attributeResourceId = 0;
    private boolean showText;
    private float textSize;
    private int textColor;
    private int innerBottomTextColor;
    private int progress = 0;
    private int max;
    private int finishedStrokeColor;
    private int unfinishedStrokeColor;
    private int startingDegree;
    private float finishedStrokeWidth;
    private float unfinishedStrokeWidth;
    private int innerBackgroundColor;
    private String prefixText = "";
    private String suffixText = "";
    private String text = null;
    private float innerBottomTextSize;
    private String innerBottomText;
    private float innerBottomTextHeight;

    private final float default_stroke_width;
    private final int default_finished_color = Color.rgb(66, 145, 241);
    private final int default_unfinished_color = Color.rgb(204, 204, 204);
    private final int default_text_color = Color.rgb(66, 145, 241);
    private final int default_inner_bottom_text_color = Color.rgb(66, 145, 241);
    private final int default_inner_background_color = Color.TRANSPARENT;
    private final int default_max = 100;
    private final int default_startingDegree = 0;
    private final float default_text_size;
    private final float default_inner_bottom_text_size;
    private final int min_size;


    private static final String INSTANCE_STATE = "saved_instance";
    private static final String INSTANCE_TEXT_COLOR = "text_color";
    private static final String INSTANCE_TEXT_SIZE = "text_size";
    private static final String INSTANCE_TEXT = "text";
    private static final String INSTANCE_INNER_BOTTOM_TEXT_SIZE = "inner_bottom_text_size";
    private static final String INSTANCE_INNER_BOTTOM_TEXT = "inner_bottom_text";
    private static final String INSTANCE_INNER_BOTTOM_TEXT_COLOR = "inner_bottom_text_color";
    private static final String INSTANCE_FINISHED_STROKE_COLOR = "finished_stroke_color";
    private static final String INSTANCE_UNFINISHED_STROKE_COLOR = "unfinished_stroke_color";
    private static final String INSTANCE_MAX = "max";
    private static final String INSTANCE_PROGRESS = "progress";
    private static final String INSTANCE_SUFFIX = "suffix";
    private static final String INSTANCE_PREFIX = "prefix";
    private static final String INSTANCE_FINISHED_STROKE_WIDTH = "finished_stroke_width";
    private static final String INSTANCE_UNFINISHED_STROKE_WIDTH = "unfinished_stroke_width";
    private static final String INSTANCE_BACKGROUND_COLOR = "inner_background_color";
    private static final String INSTANCE_STARTING_DEGREE = "starting_degree";
    private static final String INSTANCE_INNER_DRAWABLE = "inner_drawable";

    public DonutProgress(Context context) {
        this(context, null);
    }

    public DonutProgress(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public DonutProgress(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        default_text_size = Utils.sp2px(getResources(), 18);
        min_size = (int) Utils.dp2px(getResources(), 100);
        default_stroke_width = Utils.dp2px(getResources(), 10);
        default_inner_bottom_text_size = Utils.sp2px(getResources(), 18);

        final TypedArray attributes = context.getTheme().obtainStyledAttributes(attrs, R.styleable.DonutProgress, defStyleAttr, 0);
        initByAttributes(attributes);
        attributes.recycle();

        initPainters();
    }

    protected void initPainters() {
        if (showText) {
            textPaint = new TextPaint();
            textPaint.setColor(textColor);
            textPaint.setTextSize(textSize);
            textPaint.setAntiAlias(true);

            innerBottomTextPaint = new TextPaint();
            innerBottomTextPaint.setColor(innerBottomTextColor);
            innerBottomTextPaint.setTextSize(innerBottomTextSize);
            innerBottomTextPaint.setAntiAlias(true);
        }

        finishedPaint = new Paint();
        finishedPaint.setColor(finishedStrokeColor);
        finishedPaint.setStyle(Paint.Style.STROKE);
        finishedPaint.setAntiAlias(true);
        finishedPaint.setStrokeWidth(finishedStrokeWidth);

        unfinishedPaint = new Paint();
        unfinishedPaint.setColor(unfinishedStrokeColor);
        unfinishedPaint.setStyle(Paint.Style.STROKE);
        unfinishedPaint.setAntiAlias(true);
        unfinishedPaint.setStrokeWidth(unfinishedStrokeWidth);

        innerCirclePaint = new Paint();
        innerCirclePaint.setColor(innerBackgroundColor);
        innerCirclePaint.setAntiAlias(true);
    }

    protected void initByAttributes(TypedArray attributes) {
        finishedStrokeColor = attributes.getColor(R.styleable.DonutProgress_donut_finished_color, default_finished_color);
        unfinishedStrokeColor = attributes.getColor(R.styleable.DonutProgress_donut_unfinished_color, default_unfinished_color);
        showText = attributes.getBoolean(R.styleable.DonutProgress_donut_show_text, true);
        attributeResourceId = attributes.getResourceId(R.styleable.DonutProgress_donut_inner_drawable, 0);

        setMax(attributes.getInt(R.styleable.DonutProgress_donut_max, default_max));
        setProgress(attributes.getInt(R.styleable.DonutProgress_donut_progress, 0));
        finishedStrokeWidth = attributes.getDimension(R.styleable.DonutProgress_donut_finished_stroke_width, default_stroke_width);
        unfinishedStrokeWidth = attributes.getDimension(R.styleable.DonutProgress_donut_unfinished_stroke_width, default_stroke_width);

        if (showText) {
            if (attributes.getString(R.styleable.DonutProgress_donut_prefix_text) != null) {
                prefixText = attributes.getString(R.styleable.DonutProgress_donut_prefix_text);
            }
            if (attributes.getString(R.styleable.DonutProgress_donut_suffix_text) != null) {
                suffixText = attributes.getString(R.styleable.DonutProgress_donut_suffix_text);
            }
            if (attributes.getString(R.styleable.DonutProgress_donut_text) != null) {
                text = attributes.getString(R.styleable.DonutProgress_donut_text);
            }

            textColor = attributes.getColor(R.styleable.DonutProgress_donut_text_color, default_text_color);
            textSize = attributes.getDimension(R.styleable.DonutProgress_donut_text_size, default_text_size);
            innerBottomTextSize = attributes.getDimension(R.styleable.DonutProgress_donut_inner_bottom_text_size, default_inner_bottom_text_size);
            innerBottomTextColor = attributes.getColor(R.styleable.DonutProgress_donut_inner_bottom_text_color, default_inner_bottom_text_color);
            innerBottomText = attributes.getString(R.styleable.DonutProgress_donut_inner_bottom_text);
        }

        innerBottomTextSize = attributes.getDimension(R.styleable.DonutProgress_donut_inner_bottom_text_size, default_inner_bottom_text_size);
        innerBottomTextColor = attributes.getColor(R.styleable.DonutProgress_donut_inner_bottom_text_color, default_inner_bottom_text_color);
        innerBottomText = attributes.getString(R.styleable.DonutProgress_donut_inner_bottom_text);

        startingDegree = attributes.getInt(R.styleable.DonutProgress_donut_circle_starting_degree, default_startingDegree);
        innerBackgroundColor = attributes.getColor(R.styleable.DonutProgress_donut_background_color, default_inner_background_color);
    }

    @Override
    public void invalidate() {
        initPainters();
        super.invalidate();
    }

    public boolean isShowText() {
        return showText;
    }

    public void setShowText(boolean showText) {
        this.showText = showText;
    }

    public float getFinishedStrokeWidth() {
        return finishedStrokeWidth;
    }

    public void setFinishedStrokeWidth(float finishedStrokeWidth) {
        this.finishedStrokeWidth = finishedStrokeWidth;
        this.invalidate();
    }

    public float getUnfinishedStrokeWidth() {
        return unfinishedStrokeWidth;
    }

    public void setUnfinishedStrokeWidth(float unfinishedStrokeWidth) {
        this.unfinishedStrokeWidth = unfinishedStrokeWidth;
        this.invalidate();
    }

    private float getProgressAngle() {
        return getProgress() / (float) max * 360f;
    }

    public float getProgress() {
        return progress;
    }

    public void setProgress(int progress) {
        this.progress = progress;
        if (this.progress &amp;gt; getMax()) {
            this.progress %= getMax();
        }
        invalidate();
    }

    public int getMax() {
        return max;
    }

    public void setMax(int max) {
        if (max &amp;gt; 0) {
            this.max = max;
            invalidate();
        }
    }

    public float getTextSize() {
        return textSize;
    }

    public void setTextSize(float textSize) {
        this.textSize = textSize;
        this.invalidate();
    }

    public int getTextColor() {
        return textColor;
    }

    public void setTextColor(int textColor) {
        this.textColor = textColor;
        this.invalidate();
    }

    public int getFinishedStrokeColor() {
        return finishedStrokeColor;
    }

    public void setFinishedStrokeColor(int finishedStrokeColor) {
        this.finishedStrokeColor = finishedStrokeColor;
        this.invalidate();
    }

    public int getUnfinishedStrokeColor() {
        return unfinishedStrokeColor;
    }

    public void setUnfinishedStrokeColor(int unfinishedStrokeColor) {
        this.unfinishedStrokeColor = unfinishedStrokeColor;
        this.invalidate();
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
        this.invalidate();
    }

    public String getSuffixText() {
        return suffixText;
    }

    public void setSuffixText(String suffixText) {
        this.suffixText = suffixText;
        this.invalidate();
    }

    public String getPrefixText() {
        return prefixText;
    }

    public void setPrefixText(String prefixText) {
        this.prefixText = prefixText;
        this.invalidate();
    }

    public int getInnerBackgroundColor() {
        return innerBackgroundColor;
    }

    public void setInnerBackgroundColor(int innerBackgroundColor) {
        this.innerBackgroundColor = innerBackgroundColor;
        this.invalidate();
    }


    public String getInnerBottomText() {
        return innerBottomText;
    }

    public void setInnerBottomText(String innerBottomText) {
        this.innerBottomText = innerBottomText;
        this.invalidate();
    }


    public float getInnerBottomTextSize() {
        return innerBottomTextSize;
    }

    public void setInnerBottomTextSize(float innerBottomTextSize) {
        this.innerBottomTextSize = innerBottomTextSize;
        this.invalidate();
    }

    public int getInnerBottomTextColor() {
        return innerBottomTextColor;
    }

    public void setInnerBottomTextColor(int innerBottomTextColor) {
        this.innerBottomTextColor = innerBottomTextColor;
        this.invalidate();
    }

    public int getStartingDegree() {
        return startingDegree;
    }

    public void setStartingDegree(int startingDegree) {
        this.startingDegree = startingDegree;
        this.invalidate();
    }

    public int getAttributeResourceId() {
        return attributeResourceId;
    }

    public void setAttributeResourceId(int attributeResourceId) {
        this.attributeResourceId = attributeResourceId;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(measure(widthMeasureSpec), measure(heightMeasureSpec));

        //TODO calculate inner circle height and then position bottom text at the bottom (3/4)
        innerBottomTextHeight = getHeight() - (getHeight() * 3) / 4;
    }

    private int measure(int measureSpec) {
        int result;
        int mode = MeasureSpec.getMode(measureSpec);
        int size = MeasureSpec.getSize(measureSpec);
        if (mode == MeasureSpec.EXACTLY) {
            result = size;
        } else {
            result = min_size;
            if (mode == MeasureSpec.AT_MOST) {
                result = Math.min(result, size);
            }
        }
        return result;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        float delta = Math.max(finishedStrokeWidth, unfinishedStrokeWidth);
        finishedOuterRect.set(delta,
                delta,
                getWidth() - delta,
                getHeight() - delta);
        unfinishedOuterRect.set(delta,
                delta,
                getWidth() - delta,
                getHeight() - delta);

        float innerCircleRadius = (getWidth() - Math.min(finishedStrokeWidth, unfinishedStrokeWidth) + Math.abs(finishedStrokeWidth - unfinishedStrokeWidth)) / 2f;
        canvas.drawCircle(getWidth() / 2.0f, getHeight() / 2.0f, innerCircleRadius, innerCirclePaint);
        canvas.drawArc(finishedOuterRect, getStartingDegree(), getProgressAngle(), false, finishedPaint);
        canvas.drawArc(unfinishedOuterRect, getStartingDegree() + getProgressAngle(), 360 - getProgressAngle(), false, unfinishedPaint);

        if (showText) {
            String text = this.text != null ? this.text : prefixText + progress + suffixText;
            if (!TextUtils.isEmpty(text)) {
                float textHeight = textPaint.descent() + textPaint.ascent();
                canvas.drawText(text, (getWidth() - textPaint.measureText(text)) / 2.0f, (getWidth() - textHeight) / 2.0f, textPaint);
            }

            if (!TextUtils.isEmpty(getInnerBottomText())) {
                innerBottomTextPaint.setTextSize(innerBottomTextSize);
                float bottomTextBaseline = getHeight() - innerBottomTextHeight - (textPaint.descent() + textPaint.ascent()) / 2;
                canvas.drawText(getInnerBottomText(), (getWidth() - innerBottomTextPaint.measureText(getInnerBottomText())) / 2.0f, bottomTextBaseline, innerBottomTextPaint);
            }
        }

        if (attributeResourceId != 0) {
            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), attributeResourceId);
            canvas.drawBitmap(bitmap, (getWidth() - bitmap.getWidth()) / 2.0f, (getHeight() - bitmap.getHeight()) / 2.0f, null);
        }
    }

    @Override
    protected Parcelable onSaveInstanceState() {
        final Bundle bundle = new Bundle();
        bundle.putParcelable(INSTANCE_STATE, super.onSaveInstanceState());
        bundle.putInt(INSTANCE_TEXT_COLOR, getTextColor());
        bundle.putFloat(INSTANCE_TEXT_SIZE, getTextSize());
        bundle.putFloat(INSTANCE_INNER_BOTTOM_TEXT_SIZE, getInnerBottomTextSize());
        bundle.putFloat(INSTANCE_INNER_BOTTOM_TEXT_COLOR, getInnerBottomTextColor());
        bundle.putString(INSTANCE_INNER_BOTTOM_TEXT, getInnerBottomText());
        bundle.putInt(INSTANCE_INNER_BOTTOM_TEXT_COLOR, getInnerBottomTextColor());
        bundle.putInt(INSTANCE_FINISHED_STROKE_COLOR, getFinishedStrokeColor());
        bundle.putInt(INSTANCE_UNFINISHED_STROKE_COLOR, getUnfinishedStrokeColor());
        bundle.putInt(INSTANCE_MAX, getMax());
        bundle.putInt(INSTANCE_STARTING_DEGREE, getStartingDegree());
        bundle.putFloat(INSTANCE_PROGRESS, getProgress());
        bundle.putString(INSTANCE_SUFFIX, getSuffixText());
        bundle.putString(INSTANCE_PREFIX, getPrefixText());
        bundle.putString(INSTANCE_TEXT, getText());
        bundle.putFloat(INSTANCE_FINISHED_STROKE_WIDTH, getFinishedStrokeWidth());
        bundle.putFloat(INSTANCE_UNFINISHED_STROKE_WIDTH, getUnfinishedStrokeWidth());
        bundle.putInt(INSTANCE_BACKGROUND_COLOR, getInnerBackgroundColor());
        bundle.putInt(INSTANCE_INNER_DRAWABLE, getAttributeResourceId());
        return bundle;
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        if (state instanceof Bundle) {
            final Bundle bundle = (Bundle) state;
            textColor = bundle.getInt(INSTANCE_TEXT_COLOR);
            textSize = bundle.getFloat(INSTANCE_TEXT_SIZE);
            innerBottomTextSize = bundle.getFloat(INSTANCE_INNER_BOTTOM_TEXT_SIZE);
            innerBottomText = bundle.getString(INSTANCE_INNER_BOTTOM_TEXT);
            innerBottomTextColor = bundle.getInt(INSTANCE_INNER_BOTTOM_TEXT_COLOR);
            finishedStrokeColor = bundle.getInt(INSTANCE_FINISHED_STROKE_COLOR);
            unfinishedStrokeColor = bundle.getInt(INSTANCE_UNFINISHED_STROKE_COLOR);
            finishedStrokeWidth = bundle.getFloat(INSTANCE_FINISHED_STROKE_WIDTH);
            unfinishedStrokeWidth = bundle.getFloat(INSTANCE_UNFINISHED_STROKE_WIDTH);
            innerBackgroundColor = bundle.getInt(INSTANCE_BACKGROUND_COLOR);
            attributeResourceId = bundle.getInt(INSTANCE_INNER_DRAWABLE);
            initPainters();
            setMax(bundle.getInt(INSTANCE_MAX));
            setStartingDegree(bundle.getInt(INSTANCE_STARTING_DEGREE));
            setProgress(bundle.getInt(INSTANCE_PROGRESS));
            suffixText = bundle.getString(INSTANCE_SUFFIX);
            prefixText = bundle.getString(INSTANCE_PREFIX);
            text = bundle.getString(INSTANCE_TEXT);
            super.onRestoreInstanceState(bundle.getParcelable(INSTANCE_STATE));
            return;
        }
        super.onRestoreInstanceState(state);
    }
    public void setDonut_progress(String percent){
        if(!TextUtils.isEmpty(percent)){
            setProgress(Integer.parseInt(percent));
        }
    }

}

&lt;/code&gt;
&lt;/pre&gt;
Kemudian kelas &lt;b&gt;Utils.java
&lt;/b&gt;
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
import android.content.res.Resources;

/**
 * Created by bruce on 14-11-6.
 */

public final class Utils {

    private Utils() {
    }

    public static float dp2px(Resources resources, float dp) {
        final float scale = resources.getDisplayMetrics().density;
        return  dp * scale + 0.5f;
    }

    public static float sp2px(Resources resources, float sp){
        final float scale = resources.getDisplayMetrics().scaledDensity;
        return sp * scale;
    }

}
&lt;/code&gt;
&lt;/pre&gt;
Buat layout dengan nama &lt;b&gt;activity_main.xml&lt;/b&gt;. Untuk memanggil custom view harus diikuti dengan nama package.
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:custom="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="id.co.blogspot.wimsonevel.countdown_animation.MainActivity"&amp;gt;

    &amp;lt;id.co.blogspot.wimsonevel.countdown_animation.DonutProgress
        android:id="@+id/countdown_progress"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        custom:donut_progress="10"
        custom:donut_max="10"
        custom:donut_circle_starting_degree="270"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true" /&amp;gt;

    &amp;lt;Button
        android:id="@+id/btn_start"
        android:text="@string/start"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/countdown_progress"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="64dp" /&amp;gt;

&amp;lt;/RelativeLayout&amp;gt;
&lt;/code&gt;
&lt;/pre&gt;
Tambahkan beberapa resource values berikut :&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;b&gt;attrs.xml
&lt;/b&gt;&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;resources&amp;gt;

    &amp;lt;declare-styleable name="DonutProgress"&amp;gt;
        &amp;lt;attr name="donut_progress" format="integer"/&amp;gt;
        &amp;lt;attr name="donut_max" format="integer"/&amp;gt;

        &amp;lt;attr name="donut_unfinished_color" format="color"/&amp;gt;
        &amp;lt;attr name="donut_finished_color" format="color"/&amp;gt;

        &amp;lt;attr name="donut_finished_stroke_width" format="dimension"/&amp;gt;
        &amp;lt;attr name="donut_unfinished_stroke_width" format="dimension"/&amp;gt;

        &amp;lt;attr name="donut_text_size" format="dimension"/&amp;gt;
        &amp;lt;attr name="donut_text_color" format="color"/&amp;gt;

        &amp;lt;attr name="donut_prefix_text" format="string"/&amp;gt;
        &amp;lt;attr name="donut_suffix_text" format="string"/&amp;gt;
        &amp;lt;attr name="donut_text" format="string"/&amp;gt;

        &amp;lt;attr name="donut_background_color" format="color"/&amp;gt;

        &amp;lt;attr name="donut_inner_bottom_text" format="string"/&amp;gt;
        &amp;lt;attr name="donut_inner_bottom_text_size" format="dimension"/&amp;gt;
        &amp;lt;attr name="donut_inner_bottom_text_color" format="color"/&amp;gt;

        &amp;lt;attr name="donut_circle_starting_degree" format="integer" /&amp;gt;
        &amp;lt;attr name="donut_show_text" format="boolean"/&amp;gt;
        &amp;lt;attr name="donut_inner_drawable" format="reference"/&amp;gt;
    &amp;lt;/declare-styleable&amp;gt;

&amp;lt;/resources&amp;gt;
&lt;/code&gt;
&lt;/pre&gt;
&lt;b&gt;strings.xml
&lt;/b&gt;&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
&amp;lt;resources&amp;gt;
    &amp;lt;string name="app_name"&amp;gt;Countdown-Animation&amp;lt;/string&amp;gt;
    &amp;lt;string name="start"&amp;gt;Start&amp;lt;/string&amp;gt;
    &amp;lt;string name="stop"&amp;gt;Stop&amp;lt;/string&amp;gt;
    &amp;lt;string name="reset"&amp;gt;Reset&amp;lt;/string&amp;gt;
&amp;lt;/resources&amp;gt;
&lt;/code&gt;
&lt;/pre&gt;
Terakhir implementasikan &lt;b&gt;CountDownTimer&lt;/b&gt; di kelas &lt;b&gt;MainActivity.java&lt;/b&gt; berikut :
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
import android.os.CountDownTimer;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    private CountDownTimer countDownTimer;
    private DonutProgress countDownProgress;
    private Button btnStart;

    private int status = 0;
    private final long startTime = 10 * 1000;
    private final long interval = 1 * 1000;

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

        countDownProgress = (DonutProgress) findViewById(R.id.countdown_progress);
        btnStart = (Button) findViewById(R.id.btn_start);

        countDownProgress.setProgress(10);

        btnStart.setOnClickListener(this);

        countDownTimer = new CountDownTimer(startTime, interval) {
            @Override
            public void onTick(long millisUntilFinished) {
                countDownProgress.setProgress((int) millisUntilFinished / 1000);
            }

            @Override
            public void onFinish() {
                countDownProgress.setProgress(0);
                status = 2;
                btnStart.setText(R.string.reset);
            }
        };
    }

    @Override
    public void onClick(View view) {
        if (status == 0) {
            countDownTimer.start();
            status = 1;
            btnStart.setText(R.string.stop);
        } else if(status == 1){
            countDownTimer.cancel();
            countDownProgress.setProgress(10);
            status = 0;
            btnStart.setText(R.string.start);
        } else {
            countDownProgress.setProgress(10);
            status = 0;
            btnStart.setText(R.string.start);
        }
    }
}

&lt;/code&gt;
&lt;/pre&gt;
Build dan jalankan maka hasilnya sebagai berikut :
&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiXo43tnPDbv5BoW60Qjns3F4ML3WslfahX_vj6VUQMKYId4ujXuxIG6klu2qQatEjPp0UuWuD959tNw46GszVbGfB28aapdSAbIVFZVyIWUi4bWl_NnYBpqquvOQrnUbmx5ztmm316N8/s1600/Screenshot_1502358852.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="1600" data-original-width="900" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiXo43tnPDbv5BoW60Qjns3F4ML3WslfahX_vj6VUQMKYId4ujXuxIG6klu2qQatEjPp0UuWuD959tNw46GszVbGfB28aapdSAbIVFZVyIWUi4bWl_NnYBpqquvOQrnUbmx5ztmm316N8/s400/Screenshot_1502358852.png" width="225" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Source code bisa di download di &lt;a href="https://github.com/wimsonevel/Countdown-Animation"&gt;https://github.com/wimsonevel/Countdown-Animation&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Sekian tutorial kali ini semoga bermanfaat.&lt;br /&gt;
Jangan lupa share ke sosial media kalian ya :)</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHGejdwRyUsycu7gu8Gir1s3wEOXUo2NizwCmcfaPUgwRTS_ap-G_WiY4t499S7paEgknR7cIoi8We-9xthZTbP8xvgFUj4HmA4nO-PjYIGeoD0DR9u2TYaFYXfEOfFXTk8kLBu5a_FXw/s72-c/android+countdown.png" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>(Tutorial Android) Download Image to External Storage using Picasso</title><link>http://wimsonevel.blogspot.com/2017/07/tutorial-android-download-image-to.html</link><category>Android</category><author>noreply@blogger.com (Wim Sonevel)</author><pubDate>Sat, 29 Jul 2017 21:00:00 +0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-6966757688576433754.post-8108205780547266774</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4qGDrvM7Bc6XSLfvRX24vncMpr1ntW_Js59rO2eyzR5Vcu38ieyk6Zs-DJmxN-lOkGDTST4T12eexhZqsHDVjFkniFjEKAJVGclMR3RkeqzTWOqinCZ-kYLqUrbLGoE3Im1hJnhFsYiE/s1600/android+picasso+download.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="800" data-original-width="1280" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4qGDrvM7Bc6XSLfvRX24vncMpr1ntW_Js59rO2eyzR5Vcu38ieyk6Zs-DJmxN-lOkGDTST4T12eexhZqsHDVjFkniFjEKAJVGclMR3RkeqzTWOqinCZ-kYLqUrbLGoE3Im1hJnhFsYiE/s640/android+picasso+download.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Pada tutorial sebelumnya &lt;a href="http://wimsonevel.blogspot.co.id/2016/05/tutorial-android-image-loader-using.html"&gt;http://wimsonevel.blogspot.co.id/2016/05/tutorial-android-image-loader-using.html&lt;/a&gt; saya menjelaskan bagaimana penggunaan library &lt;b&gt;Picasso&lt;/b&gt; sebagai library Image Loader yang berfungsi menampilkan gambar dari penyimpanan lokal maupun link url. Nah, pada kesempatan kali ini saya akan membagikan sedikit code agar gambar yang sudah di-load oleh Picasso bisa didownload atau disimpan di memori penyimpanan.&lt;br /&gt;
&lt;br /&gt;
Langsung aja ke TKP.&lt;br /&gt;
&lt;br /&gt;
Pertama buat project baru agan-agan.&lt;br /&gt;
&lt;br /&gt;
Tambahkan library &lt;b&gt;Picasso&lt;/b&gt; di build.gradle&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:25.3.1'
    compile 'com.squareup.picasso:picasso:2.5.2'
    testCompile 'junit:junit:4.12'
}
&lt;/code&gt;
&lt;/pre&gt;
Kedua buat layout dengan &lt;b&gt;activity_main.xml&lt;/b&gt; dengan komponen &lt;b&gt;Image View&lt;/b&gt; dan &lt;b&gt;Button&lt;/b&gt;.
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="id.co.blogspot.wimsonevel.android_picassodownload.MainActivity"&amp;gt;

    &amp;lt;ImageView
        android:id="@+id/iv_image"
        android:layout_width="300dp"
        android:layout_height="400dp"
        android:layout_gravity="center"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:layout_above="@+id/btn_save"
        tools:ignore="ContentDescription" /&amp;gt;

    &amp;lt;Button
        android:id="@+id/btn_save"
        android:text="@string/save_image"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true" /&amp;gt;

&amp;lt;/RelativeLayout&amp;gt;

&lt;/code&gt;
&lt;/pre&gt;
Kemudian beberapa resouce lainnya berikut :&lt;br /&gt;
&lt;br /&gt;
colors.xml
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;resources&amp;gt;
    &amp;lt;color name="colorPrimary"&amp;gt;#b94948&amp;lt;/color&amp;gt;
    &amp;lt;color name="colorPrimaryDark"&amp;gt;#b94948&amp;lt;/color&amp;gt;
    &amp;lt;color name="colorAccent"&amp;gt;#FF4081&amp;lt;/color&amp;gt;
&amp;lt;/resources&amp;gt;
&lt;/code&gt;
&lt;/pre&gt;
strings.xml
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
&amp;lt;resources&amp;gt;
    &amp;lt;string name="app_name"&amp;gt;Android-PicassoDownload&amp;lt;/string&amp;gt;

    &amp;lt;string name="save_image"&amp;gt;Save Image&amp;lt;/string&amp;gt;

&amp;lt;/resources&amp;gt;
&lt;/code&gt;
&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style="font-size: large;"&gt;Picasso Target
&lt;/span&gt;&lt;/b&gt;
&lt;br /&gt;
&lt;b&gt;Picasso&lt;/b&gt; menyediakan sebuat interface &lt;b&gt;Target&lt;/b&gt; yang menyediakan &lt;b&gt;callback&lt;/b&gt; &lt;b&gt;bitmap&lt;/b&gt; sehingga kita dapat memanfaatkan bitmap dari image untuk diproses lebih lanjut.
&lt;br /&gt;
&lt;br /&gt;
Contoh penggunaannya :
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
Picasso.with(this)
        .load(url)
        .into(new Target() {
            @Override
            public void onBitmapLoaded(final Bitmap bitmap, Picasso.LoadedFrom from) {
                
            }

            @Override
            public void onBitmapFailed(Drawable errorDrawable) {

            }

            @Override
            public void onPrepareLoad(Drawable placeHolderDrawable) {
            }
        });
&lt;/code&gt;
&lt;/pre&gt;
Hasil bitmap lalu kita proses untuk dijadikan sebuah file image &lt;b&gt;ber-ekstensi jpg&lt;/b&gt;. Kemudian disimpan di direktori folder memori eksternal yang kita inginkan. Contohnya saya menyimpan file image di folder &lt;b&gt;Pictures&lt;/b&gt;.
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
File sd = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File folder = new File(sd, "/PicassoDownload/");
if (!folder.exists()) {
    if (!folder.mkdir()) {
        Log.e("ERROR", "Cannot create a directory!");
    } else {
        folder.mkdir();
    }
}
File fileName = new File(folder, imgName);
try {
    fileName.createNewFile();
    FileOutputStream ostream = new FileOutputStream(fileName);
    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, ostream);
    ostream.close();
} catch (Exception e) {
    e.printStackTrace();
}
&lt;/code&gt;
&lt;/pre&gt;
Buat activity dengan nama &lt;b&gt;MainActivity.java&lt;/b&gt;, implementasikan code di atas di dalamnya ketika tombol save diklik. Untuk memodifikasi baik itu membaca maupun menulis file di memori eksternal kita memerlukan &lt;b&gt;permission&lt;/b&gt;, di &lt;b&gt;Android versi M&lt;/b&gt; ke atas perlu adanya pengecekan permission secara runtime. &lt;br /&gt;
&lt;br /&gt;
Berikut list kode lengkapnya.
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.os.Environment;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

import com.squareup.picasso.Picasso;
import com.squareup.picasso.Target;

import java.io.File;
import java.io.FileOutputStream;

public class MainActivity extends AppCompatActivity {

    private static final int PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE = 100;
    private static final String PREF_CAMERA_REQUESTED = "cameraRequested";

    private String url;

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

        ImageView ivImage= (ImageView) findViewById(R.id.iv_image);
        Button btnSave = (Button) findViewById(R.id.btn_save);

        url = "https://scontent-sit4-1.xx.fbcdn.net/v/t1.0-9/20228885_1440264296060520_6773935769024601349_n.jpg?oh=da445041a4bc99ec499b78d39b8832eb&amp;amp;oe=5A371E89";

        Picasso.with(this)
                .load(url)
                .into(ivImage);

        btnSave.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                saveImage(url, "newfile.jpg");
            }
        });
    }

    private void saveImage(String url, final String imgName) {
        if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
                == PackageManager.PERMISSION_GRANTED) {
            Toast.makeText(this, "In progress...", Toast.LENGTH_SHORT).show();

            Picasso.with(this)
                    .load(url)
                    .into(new Target() {
                        @Override
                        public void onBitmapLoaded(final Bitmap bitmap, Picasso.LoadedFrom from) {
                            File sd = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
                            File folder = new File(sd, "/PicassoDownload/");
                            if (!folder.exists()) {
                                if (!folder.mkdir()) {
                                    Log.e("ERROR", "Cannot create a directory!");
                                } else {
                                    folder.mkdir();
                                }
                            }

                            File fileName = new File(folder, imgName);

                            try {
                                fileName.createNewFile();
                                FileOutputStream ostream = new FileOutputStream(fileName);
                                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, ostream);
                                ostream.close();
                            } catch (Exception e) {
                                e.printStackTrace();
                            }

                            Toast.makeText(MainActivity.this, "Image Saved Successfully!", Toast.LENGTH_SHORT).show();
                        }

                        @Override
                        public void onBitmapFailed(Drawable errorDrawable) {
                            Toast.makeText(MainActivity.this, "Image Failed to Save", Toast.LENGTH_SHORT).show();
                        }

                        @Override
                        public void onPrepareLoad(Drawable placeHolderDrawable) {

                        }
                    });
        } else {
            requestWriteExternalPermission();
        }
    }

    private void requestWriteExternalPermission() {
        final String[] permissions = new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE};

        if (ActivityCompat.shouldShowRequestPermissionRationale(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
            ActivityCompat.requestPermissions(this, permissions, PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE);
        } else {
            if (!isPermissionRequested(PREF_CAMERA_REQUESTED)) {
                ActivityCompat.requestPermissions(this, permissions, PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE);
                setPermissionRequested(PREF_CAMERA_REQUESTED);
            } else {
                Toast.makeText(MainActivity.this, "Please grant storage permission to save images", Toast.LENGTH_SHORT).show();
            }
        }
    }

    private void setPermissionRequested(String permission) {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
        SharedPreferences.Editor editor = preferences.edit();
        editor.putBoolean(permission, true);
        editor.apply();
    }

    private boolean isPermissionRequested(String permission) {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
        return preferences.getBoolean(permission, false);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

        switch (requestCode) {
            case PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE: {
                if (grantResults.length != 0 &amp;amp;&amp;amp; grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    Log.d("SUCCESS", "Write External permission granted");
                    saveImage(url, "newFile.jpg");
                    return;
                }
                Log.e("ERROR", "Permission not granted: results len = " + grantResults.length +
                        " Result code = " + (grantResults.length &amp;gt; 0 ? grantResults[0] : "(empty)"));
                finish();
            }
            default: {
                Log.d("ERROR", "Got unexpected permission result: " + requestCode);
                super.onRequestPermissionsResult(requestCode, permissions, grantResults);
                break;
            }
        }
    }
}
&lt;/code&gt;
&lt;/pre&gt;
Terakhir tambahkan permission di AndroidManifest.xml.
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="id.co.blogspot.wimsonevel.android_picassodownload"&amp;gt;

    &amp;lt;uses-permission android:name="android.permission.INTERNET" /&amp;gt;
    &amp;lt;uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /&amp;gt;
    &amp;lt;uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /&amp;gt;

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

                &amp;lt;category android:name="android.intent.category.LAUNCHER" /&amp;gt;
            &amp;lt;/intent-filter&amp;gt;
        &amp;lt;/activity&amp;gt;
    &amp;lt;/application&amp;gt;

&amp;lt;/manifest&amp;gt;
&lt;/code&gt;
&lt;/pre&gt;
Build dan jalankan maka hasilnya sebagai berikut :&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjy0ckcd6q7cQEEXwBKMkM7OaTjts_Jv4K1iaCkfliTMBYBlPTAoEGpBlF9wW2igSDARb03n8CQklSbvzcWVBBFHjh93C4xJ-34C9y01GEawPKUSMxuNwyCbmjEP1OqGVZGXywecTEPKtM/s1600/Screenshot_20170729-191417.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="1600" data-original-width="900" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjy0ckcd6q7cQEEXwBKMkM7OaTjts_Jv4K1iaCkfliTMBYBlPTAoEGpBlF9wW2igSDARb03n8CQklSbvzcWVBBFHjh93C4xJ-34C9y01GEawPKUSMxuNwyCbmjEP1OqGVZGXywecTEPKtM/s400/Screenshot_20170729-191417.png" width="225" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Klik &lt;b&gt;“Save Image”&lt;/b&gt; maka image akan tersimpan di folder &lt;b&gt;Pictures-&amp;gt;PicassoDownload&lt;/b&gt;&lt;br /&gt;


&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgL-bSdgJNK4vNE8rVbw1WQlMJG9Kf421YGpLe3QPcTLWEgMkP6kQBWumW2LkOXvKIUXOaFCVisGQluVb0P-85cL_4EXFH6F_FU-7TQYOZWbh22bivNDyIEnxyUXcs1a90_u0jVpWxg0OQ/s1600/file.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="854" data-original-width="1600" height="339" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgL-bSdgJNK4vNE8rVbw1WQlMJG9Kf421YGpLe3QPcTLWEgMkP6kQBWumW2LkOXvKIUXOaFCVisGQluVb0P-85cL_4EXFH6F_FU-7TQYOZWbh22bivNDyIEnxyUXcs1a90_u0jVpWxg0OQ/s640/file.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
Source code lengkap dapat dilihat di &lt;a href="https://github.com/wimsonevel/Android-PicassoDownload"&gt;https://github.com/wimsonevel/Android-PicassoDownload&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Sekian tutorial kali ini dan semoga bermanfaat.&lt;br /&gt;
Jangan lupa share ke sosial media kalian ^^</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4qGDrvM7Bc6XSLfvRX24vncMpr1ntW_Js59rO2eyzR5Vcu38ieyk6Zs-DJmxN-lOkGDTST4T12eexhZqsHDVjFkniFjEKAJVGclMR3RkeqzTWOqinCZ-kYLqUrbLGoE3Im1hJnhFsYiE/s72-c/android+picasso+download.png" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total></item><item><title>(Tutorial iOS) Custom UITableViewCell in UITableView</title><link>http://wimsonevel.blogspot.com/2017/07/tutorial-ios-custom-uitableviewcell-in.html</link><category>iOS</category><category>Swift</category><author>noreply@blogger.com (Wim Sonevel)</author><pubDate>Thu, 27 Jul 2017 14:12:00 +0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-6966757688576433754.post-6477669619834035336</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicIFSHkdxjHxYDi-oQGTt2xWQRr8PEnpSGy2i6uu4rvvVdAKUgaI4YvONTOCat_HMVafZdbGEngDFZn2LZbvkPqtNJa9tW5_61lyUh7gQfeZqwXWYmtIIgDCqYKvwK8vcJLVyKiDMh91g/s1600/ios+customuitableviewcell.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="800" data-original-width="1280" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicIFSHkdxjHxYDi-oQGTt2xWQRr8PEnpSGy2i6uu4rvvVdAKUgaI4YvONTOCat_HMVafZdbGEngDFZn2LZbvkPqtNJa9tW5_61lyUh7gQfeZqwXWYmtIIgDCqYKvwK8vcJLVyKiDMh91g/s640/ios+customuitableviewcell.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Hallo gaes, sudah lama rasanya tidak menulis tutorial tentang iOS.&lt;br /&gt;
Nah pada kesempatan kali ini saya akan coba membahas tentang &lt;b&gt;UITableView&lt;/b&gt;. UITableView merupakan widget yang biasa digunakan untuk menampilkan data dalam bentuk list. Pada umumnya komponen di dalam UITableView disebut dengan &lt;b&gt;UITableViewCell&lt;/b&gt;. Komponen UITableViewCell inilah yang mengisi setiap baris-baris di dalam list. Secara default, UITabelViewCell cuma berisi title dan subtitle. Maka dari itu jika ingin membuat baris yang lebih komplek maka kita perlu membuat &lt;b&gt;custom UITableViewCell&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
Oke singkat penjelasannya di atas, sekarang langsung kita praktekkan aja.&lt;br /&gt;
&lt;br /&gt;
Pertama buat project baru di Xcode, untuk bahasa pemrogramannya menggunakan Swift 3.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtLeKlrXzp_L-w29-wapT2B7O7nbQ8bflRcf7SUi-0YUoyDb64UpNmZAtFYlziZcO-jVsqDSaV93-YWKSuoKlubMV_3iUtoJ4UIce_uhdufJ_YcSLS4jN3-MeH_9gMEy8MD5pgMV8DUtY/s1600/Screen+Shot+2017-07-27+at+1.12.40+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="1040" data-original-width="1460" height="283" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtLeKlrXzp_L-w29-wapT2B7O7nbQ8bflRcf7SUi-0YUoyDb64UpNmZAtFYlziZcO-jVsqDSaV93-YWKSuoKlubMV_3iUtoJ4UIce_uhdufJ_YcSLS4jN3-MeH_9gMEy8MD5pgMV8DUtY/s400/Screen+Shot+2017-07-27+at+1.12.40+PM.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Kemudian pada halaman storyboard-nya kita menggunakan &lt;b&gt;Table View Controller&lt;/b&gt;. Drag and drop Table View Controller ke halaman &lt;b&gt;storyboard&lt;/b&gt;, lalu jadikan sebagai &lt;b&gt;Root View Controller&lt;/b&gt; (alias tanda panah berada di Table View Controller). &lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnvppEaUUBeEpCqbqzb7Ega9qedL4lZXfNi0eLuyv-YF19B0Xuqx-_w0mQuat5aSqZ8jOI0C3HAFUkzEz_yvmE5MnrPvSAtLqnWdeqVYeJ84v4SI6fXLWmwF_DFFFHwdz1AlZpc_P03D4/s1600/Screen+Shot+2017-07-21+at+9.09.31+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="660" data-original-width="520" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnvppEaUUBeEpCqbqzb7Ega9qedL4lZXfNi0eLuyv-YF19B0Xuqx-_w0mQuat5aSqZ8jOI0C3HAFUkzEz_yvmE5MnrPvSAtLqnWdeqVYeJ84v4SI6fXLWmwF_DFFFHwdz1AlZpc_P03D4/s320/Screen+Shot+2017-07-21+at+9.09.31+PM.png" width="252" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibHuFcWp8avei2cvUHEXhL4XJEOY0Toude5ZoAnAtO3WB5ZuToRIvEXJtSB5KROUk0vJrZv2SgGHVwEmDlZNr9hIcwIyt4u4fX3l-mC-1AktHxLq2dXm1uf27G7y9cO9lmX974oQCGp-0/s1600/Screen+Shot+2017-07-21+at+9.09.09+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="1292" data-original-width="1518" height="544" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibHuFcWp8avei2cvUHEXhL4XJEOY0Toude5ZoAnAtO3WB5ZuToRIvEXJtSB5KROUk0vJrZv2SgGHVwEmDlZNr9hIcwIyt4u4fX3l-mC-1AktHxLq2dXm1uf27G7y9cO9lmX974oQCGp-0/s640/Screen+Shot+2017-07-21+at+9.09.09+PM.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Setelah itu tambahkan beberapa widget di dalam Table View Cell, contohnya di sini kita menambahkan &lt;b&gt;Image View&lt;/b&gt; dan &lt;b&gt;Label&lt;/b&gt;. Lalu letakkan dengan posisi sebagai berikut :&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiscQRKouYrMKGQVLQZS4mMYK0YnP9klVuGmXJLCIGhitj5kgCUAoUXGFQMdd7k3gRYmllKGqXBD856_JbbieWPRgbtadRdKHOe2eJ6XKnX3qZ12QKoKN1hs9rIZgOAWS37YgE3slEqja8/s1600/Screen+Shot+2017-07-26+at+8.53.16+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="912" data-original-width="1476" height="394" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiscQRKouYrMKGQVLQZS4mMYK0YnP9klVuGmXJLCIGhitj5kgCUAoUXGFQMdd7k3gRYmllKGqXBD856_JbbieWPRgbtadRdKHOe2eJ6XKnX3qZ12QKoKN1hs9rIZgOAWS37YgE3slEqja8/s640/Screen+Shot+2017-07-26+at+8.53.16+PM.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;b&gt;Embed&lt;/b&gt; Table View Controller tadi ke dalam &lt;b&gt;Navigation Controller&lt;/b&gt; dengan cara klik menu &lt;b&gt;Editor&lt;/b&gt; → &lt;b&gt;Embed in&lt;/b&gt; → &lt;b&gt;Navigation Controller&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwgHGGEY93tfBHP2WjTX-vOY1e3iTFUayT_DlXHLx15-FP3iU-Pg-zzEhstOFJyxjKo24oYLuHxn8bCpzsSryjCGHQDBBsZaC7Q6GmaJoiEb5hhzVIrCWJKVPyUMCl2mnQt-8v3ecHiYk/s1600/Screen+Shot+2017-07-27+at+1.34.32+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="966" data-original-width="944" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwgHGGEY93tfBHP2WjTX-vOY1e3iTFUayT_DlXHLx15-FP3iU-Pg-zzEhstOFJyxjKo24oYLuHxn8bCpzsSryjCGHQDBBsZaC7Q6GmaJoiEb5hhzVIrCWJKVPyUMCl2mnQt-8v3ecHiYk/s320/Screen+Shot+2017-07-27+at+1.34.32+PM.png" width="312" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0RWTmVpd7mrqcsz3fFCIEPYcQX6WjrOGqn8SFs-bheU1UNTVby2RQ1uoTt7cQlcwD3IakCoV1pxGkj0uFYrzOKnLoK7ECcP_5IBUY5kevcYqmbeUQbsO1PUGHOXYYGIk3azEAv8MKW3Y/s1600/Screen+Shot+2017-07-27+at+1.34.09+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="860" data-original-width="1524" height="360" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0RWTmVpd7mrqcsz3fFCIEPYcQX6WjrOGqn8SFs-bheU1UNTVby2RQ1uoTt7cQlcwD3IakCoV1pxGkj0uFYrzOKnLoK7ECcP_5IBUY5kevcYqmbeUQbsO1PUGHOXYYGIk3azEAv8MKW3Y/s640/Screen+Shot+2017-07-27+at+1.34.09+PM.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
Sekarang kita masuk ke sesi codingnya. Buka file &lt;b&gt;ViewController.swif&lt;/b&gt;t kemudian implement &lt;b&gt;UITableViewController&lt;/b&gt; seperti berikut :&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
import UIKit

class ViewController: UITableViewController {

    var foods = [Food(thumb: "rendang", name: "Rendang", country: "Indonesia"),
                 Food(thumb: "nasi_goreng", name: "Nasi Goreng", country: "Indonesia"),
                 Food(thumb: "sushi", name: "Sushi", country: "Japan"),
                 Food(thumb: "tom_yum_goong", name: "Tom Yum Goong", country: "Thailand"),
                 Food(thumb: "pad_thai", name: "Pad Thai", country: "Thailand"),
                 Food(thumb: "som_tam", name: "Som Tam", country: "Thailand"),
                 Food(thumb: "dim_sum", name: "Dim Sum", country: "Hongkong"),
                 Food(thumb: "ramen", name: "Ramen", country: "Japan"),
                 Food(thumb: "peking_duck", name: "Peking Duck", country: "China"),
                 Food(thumb: "massaman_curry", name: "Massaman Curry", country: "Thailand")]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}
&lt;/code&gt;
&lt;/pre&gt;
Tambahkan type struct untuk item Food.
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
struct Food {
    var thumb = String()
    var name = String()
    var country = String()
}
&lt;/code&gt;
&lt;/pre&gt;
Tambahkan class CustomCell.
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
class CustomCell: UITableViewCell {

    @IBOutlet weak var thumbImageView: UIImageView!
    @IBOutlet weak var nameLabel: UILabel!
    @IBOutlet weak var countryLabel: UILabel!
    
}
&lt;/code&gt;
&lt;/pre&gt;
Kemudian reference komponen dari Table View Cell di storyboard ke kelas CustomCell di atas.
&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfYh1U67KYFzJILA5rIxYTa7-qxXdICWZZ8jAUKd-dIBBQjMNT5hp5nxTodyWyCQyvDCDVhQ7QbdPwPwZBPgEQ6QYpeJ7eDFOIDXIoQk7GgwzLdO2z47HZJJMZ1saMlY0_9wzgQxf9Lxs/s1600/Screen+Shot+2017-07-27+at+1.21.40+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="716" data-original-width="520" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfYh1U67KYFzJILA5rIxYTa7-qxXdICWZZ8jAUKd-dIBBQjMNT5hp5nxTodyWyCQyvDCDVhQ7QbdPwPwZBPgEQ6QYpeJ7eDFOIDXIoQk7GgwzLdO2z47HZJJMZ1saMlY0_9wzgQxf9Lxs/s320/Screen+Shot+2017-07-27+at+1.21.40+PM.png" width="232" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiz38raBdb8oqQF6WZNB2ru50jbVO22-AvWIHDIFKf36QwI5Mh7TID3CxDv09jY-a_dzuTGfVtW0AfRug3d9NvKylDpNBOmbNtiXtBtMvB_hy_fcve18E3GMLiVvf9ia9k78uDmBdRXUcU/s1600/Screen+Shot+2017-07-27+at+1.21.09+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="880" data-original-width="1496" height="376" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiz38raBdb8oqQF6WZNB2ru50jbVO22-AvWIHDIFKf36QwI5Mh7TID3CxDv09jY-a_dzuTGfVtW0AfRug3d9NvKylDpNBOmbNtiXtBtMvB_hy_fcve18E3GMLiVvf9ia9k78uDmBdRXUcU/s640/Screen+Shot+2017-07-27+at+1.21.09+PM.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Tambahkan extension di bawahnya kemudian override beberapa function dari TableView.
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
extension ViewController {
    
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -&amp;gt; Int {
        return foods.count
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -&amp;gt; UITableViewCell {
        
        let food = foods[indexPath.row]
        
        let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell
        
        cell.thumbImageView.image = UIImage(named: food.thumb)
        
        cell.nameLabel?.text = food.name
        cell.countryLabel.text = food.country
        
        return cell

    }
    
}
&lt;/code&gt;
&lt;/pre&gt;
Source code lengkapnya jadi sebagai berikut :
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
import UIKit

class ViewController: UITableViewController {

    var foods = [Food(thumb: "rendang", name: "Rendang", country: "Indonesia"),
                 Food(thumb: "nasi_goreng", name: "Nasi Goreng", country: "Indonesia"),
                 Food(thumb: "sushi", name: "Sushi", country: "Japan"),
                 Food(thumb: "tom_yum_goong", name: "Tom Yum Goong", country: "Thailand"),
                 Food(thumb: "pad_thai", name: "Pad Thai", country: "Thailand"),
                 Food(thumb: "som_tam", name: "Som Tam", country: "Thailand"),
                 Food(thumb: "dim_sum", name: "Dim Sum", country: "Hongkong"),
                 Food(thumb: "ramen", name: "Ramen", country: "Japan"),
                 Food(thumb: "peking_duck", name: "Peking Duck", country: "China"),
                 Food(thumb: "massaman_curry", name: "Massaman Curry", country: "Thailand")]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}

struct Food {
    var thumb = String()
    var name = String()
    var country = String()
}

class CustomCell: UITableViewCell {

    @IBOutlet weak var thumbImageView: UIImageView!
    @IBOutlet weak var nameLabel: UILabel!
    @IBOutlet weak var countryLabel: UILabel!
    
}

extension ViewController {
    
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -&amp;gt; Int {
        return foods.count
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -&amp;gt; UITableViewCell {
        
        let food = foods[indexPath.row]
        
        let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell
        
        cell.thumbImageView.image = UIImage(named: food.thumb)
        
        cell.nameLabel?.text = food.name
        cell.countryLabel.text = food.country
        
        return cell

    }
    
}

&lt;/code&gt;
&lt;/pre&gt;
Build dan jalankan maka hasilnya seperti ini :&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjC6rLGYIXdlEAYlePtESXSKsjdQrv9fZ_S-aGpsrzI9bz5aBEymHqmKT1mvEbBSzCg-I6cAk93aRUA09BkvO4xN1Qpqy3asrVReAWK98cLo-Q34sGbri_GqljGF4nshqxEn6bPIdSyWFg/s1600/Simulator+Screen+Shot+Jul+27%252C+2017%252C+1.38.33+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="1136" data-original-width="640" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjC6rLGYIXdlEAYlePtESXSKsjdQrv9fZ_S-aGpsrzI9bz5aBEymHqmKT1mvEbBSzCg-I6cAk93aRUA09BkvO4xN1Qpqy3asrVReAWK98cLo-Q34sGbri_GqljGF4nshqxEn6bPIdSyWFg/s400/Simulator+Screen+Shot+Jul+27%252C+2017%252C+1.38.33+PM.png" width="225" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Source code lengkap dapat dilihat di &lt;a href="https://github.com/wimsonevel/CustomUITableViewCell"&gt;https://github.com/wimsonevel/CustomUITableViewCell&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Sekian tutorial dari saya dan semoga bermanfaat.&lt;br /&gt;
Jangan lupa share ke sosial media kalian. Thanks :)</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicIFSHkdxjHxYDi-oQGTt2xWQRr8PEnpSGy2i6uu4rvvVdAKUgaI4YvONTOCat_HMVafZdbGEngDFZn2LZbvkPqtNJa9tW5_61lyUh7gQfeZqwXWYmtIIgDCqYKvwK8vcJLVyKiDMh91g/s72-c/ios+customuitableviewcell.png" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>(Tutorial Android) Push Notification using Firebase Cloud Messaging (FCM)</title><link>http://wimsonevel.blogspot.com/2017/07/tutorial-android-push-notification.html</link><category>Android</category><author>noreply@blogger.com (Wim Sonevel)</author><pubDate>Wed, 19 Jul 2017 17:14:00 +0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-6966757688576433754.post-6573577399481338217</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7EU1Zsbj5JHJ_8jtNP430Sg2E3rQSZfRo_jZ3EB3XZ4PQ4tpnMyL792oTH4pSSCwZySitv9uGc6_ggTBkmQCq8zJwkpBFlfrQ-Ce6GbZElWPHiV2N7wAbrR8hjMh6fyH9VGoPBl_mNuU/s1600/android_fcm.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="800" data-original-width="1280" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7EU1Zsbj5JHJ_8jtNP430Sg2E3rQSZfRo_jZ3EB3XZ4PQ4tpnMyL792oTH4pSSCwZySitv9uGc6_ggTBkmQCq8zJwkpBFlfrQ-Ce6GbZElWPHiV2N7wAbrR8hjMh6fyH9VGoPBl_mNuU/s640/android_fcm.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;b&gt;Firebase Cloud Messaging&lt;/b&gt; adalah layanan push notifikasi cross-platform yang dikembangkan oleh Google yang sebelumnya menggantikan GCM, yang memungkinkan kita mengirimkan push notifikasi ke pengguna. Layanan &lt;b&gt;FCM&lt;/b&gt; ini sepenuhnya gratis dan tidak dibatasi.&lt;br /&gt;
&lt;br /&gt;
Pada tutorial kali ini saya akan membahas cara mengimplementasikan FCM di Android.&lt;br /&gt;
&lt;br /&gt;
Firebase Cloud Messaging pada umumnya memiliki beberapa tipe notifikasi. Tipe yang akan kita coba pada tutorial ini adalah &lt;b&gt;Notification Message&lt;/b&gt;. Tipe notifikasi ini merupakan tipe yang pada umumnya digunakan untuk mengirimkan push notification.&lt;br /&gt;
&lt;br /&gt;
Contoh data yang dikirimkan berupa json sebagai berikut :
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
{
    "to": "e1w6hEbZn-8:APA91bEUIb2JewYCIiApsMu5JfI5Ak...",
    "notification": {
        "body": "Hello? This is push notification :)",
        "title": "Push Notification",
        "icon": "ic_launcher"
    }
}
&lt;/code&gt;
&lt;/pre&gt;
Kita dapat juga memilih kemana kita akan mengirimkan push notification tersebut. Misal kita ingin mengirim push notification ke device tertentu bisa menggunakan FCM registration token dari device tersebut. Atau ke segment-segment tertentu bisa dengan mengirimkannya ke topics di firebase.&lt;br /&gt;
&lt;br /&gt;
Itu dia sedikit penjelasannya dari saya. Nah sekarang kita langsung praktek aja.
&lt;br /&gt;
&lt;br /&gt;
Sebelumnya buat project baru dulu di &lt;b&gt;Android Studio&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
Setelah selesai buat project baru, lalu kita harus login ke &lt;b&gt;firebase console&lt;/b&gt;. Silahkan login dulu dengan &lt;b&gt;akun&lt;/b&gt; &lt;b&gt;google&lt;/b&gt; agan-agan kemudian buka halaman &lt;a href="https://firebase.google.com/"&gt;https://firebase.google.com/&lt;/a&gt; lalu klik &lt;b&gt;Go To Console&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJANDpxmBBEDAJvamc18sE3xy0XMVmWyunmUmF6Xl5TbMRWkO2uQOuZnZh_KJwJ6gw9vkVPr5EqafQC736coOmv1COIxMhpa3nRWAwxuoPEcruVytkBJpPs9zbBJWWQh9jqq_yUmCBUBc/s1600/Screen+Shot+2017-07-15+at+2.34.24+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="737" data-original-width="1600" height="292" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJANDpxmBBEDAJvamc18sE3xy0XMVmWyunmUmF6Xl5TbMRWkO2uQOuZnZh_KJwJ6gw9vkVPr5EqafQC736coOmv1COIxMhpa3nRWAwxuoPEcruVytkBJpPs9zbBJWWQh9jqq_yUmCBUBc/s640/Screen+Shot+2017-07-15+at+2.34.24+PM.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Halaman dashboard akan tampak seperti gambar di bawah ini. Untuk membuat project baru klik &lt;b&gt;Add project&lt;/b&gt;. &lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpq4yR7C1jcU3HZETlosWq976i5bXuz1txXeLFqJWqRATJ5sNfTwetxGIqRLJspfFZrV8DK-hIFuDJee15xZIZhN_x5PxroKZc8goA-3ZoPB_FCCuR43mXoPKWB_T9blXuv0tmAteDVQI/s1600/Screen+Shot+2017-07-15+at+2.37.16+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="832" data-original-width="1600" height="332" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpq4yR7C1jcU3HZETlosWq976i5bXuz1txXeLFqJWqRATJ5sNfTwetxGIqRLJspfFZrV8DK-hIFuDJee15xZIZhN_x5PxroKZc8goA-3ZoPB_FCCuR43mXoPKWB_T9blXuv0tmAteDVQI/s640/Screen+Shot+2017-07-15+at+2.37.16+PM.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Buat project baru kemudian isi &lt;b&gt;Project name&lt;/b&gt; dan &lt;b&gt;Country&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOK2w99rzaGtbyfbHlzVrXspEM57zzOVG93YMxNbBqNwGCrB4AbHXiKajItFQmbNhhzjOyHEuVb06q4-cbsD5TMFqoRY9un48RxQdKlhp1J6fzHJeTs0etbiiaFq3TRQAI4MnQvj4I2yM/s1600/Screen+Shot+2017-07-15+at+3.57.05+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="886" data-original-width="888" height="319" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOK2w99rzaGtbyfbHlzVrXspEM57zzOVG93YMxNbBqNwGCrB4AbHXiKajItFQmbNhhzjOyHEuVb06q4-cbsD5TMFqoRY9un48RxQdKlhp1J6fzHJeTs0etbiiaFq3TRQAI4MnQvj4I2yM/s320/Screen+Shot+2017-07-15+at+3.57.05+PM.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Setelah itu masuk ke menu notification. Di sini ada 2 pilihan platform yang bisa kita pilih, berhubung tutorial kita tentang Android maka kita pilih platform &lt;b&gt;Android&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5cxfl94CpBD0V2V9ZDL5p2-pCCojtQPx4NVrMaN5m6SuVlHIbLGst_ynMmZpBijIS-lRwrbzO2BUI7eSNAfVX24LMkMIdLIl5O2n_fOSJtAj0YsdiOhsResAhus2mNWVqnNgQZRBPbL8/s1600/Screen+Shot+2017-07-15+at+3.59.30+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="797" data-original-width="1600" height="318" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5cxfl94CpBD0V2V9ZDL5p2-pCCojtQPx4NVrMaN5m6SuVlHIbLGst_ynMmZpBijIS-lRwrbzO2BUI7eSNAfVX24LMkMIdLIl5O2n_fOSJtAj0YsdiOhsResAhus2mNWVqnNgQZRBPbL8/s640/Screen+Shot+2017-07-15+at+3.59.30+PM.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Setelah itu muncul form untuk mengisi nama &lt;b&gt;package&lt;/b&gt;, &lt;b&gt;nickname&lt;/b&gt; dan &lt;b&gt;debug certificate SHA-1&lt;/b&gt;. Untuk mendapatkan &lt;b&gt;debug certificate&lt;/b&gt;, buka terminal atau command prompt dan perintahnya bisa lihat di &lt;a href="https://developers.google.com/android/guides/client-auth"&gt;https://developers.google.com/android/guides/client-auth&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvjCFBz768o314rKP3ZxcOEH70s36N31IOEi9GTduicXgBBVCccS3LxPANW3SsdyQ0EbRhSFHMsi8A2vsIlFlDwfepr9ILJkgZNt6-wVHgP1MgwM91hTKPMSYf91KjXlN8Zrde2nlkyVc/s1600/Screen+Shot+2017-07-15+at+4.06.49+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="1204" data-original-width="1380" height="348" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvjCFBz768o314rKP3ZxcOEH70s36N31IOEi9GTduicXgBBVCccS3LxPANW3SsdyQ0EbRhSFHMsi8A2vsIlFlDwfepr9ILJkgZNt6-wVHgP1MgwM91hTKPMSYf91KjXlN8Zrde2nlkyVc/s400/Screen+Shot+2017-07-15+at+4.06.49+PM.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Kemudian download &lt;b&gt;google-services.json&lt;/b&gt; lalu letakkan di dalam folder &lt;b&gt;project→app&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisevuOyq3UtkrvQPKDWBsBPdqUJyvAkScHDdwVc_mP2eFJ9VOunMDhAQbj70-M8mKQGTHkoRfT9nGE7Y5012QPVyQPlWTJ04bIKTKez_jwI8jAEmCOvxBg-xIb387yHNu0V-vs47bDLu0/s1600/Screen+Shot+2017-07-15+at+4.07.10+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="1200" data-original-width="1390" height="345" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisevuOyq3UtkrvQPKDWBsBPdqUJyvAkScHDdwVc_mP2eFJ9VOunMDhAQbj70-M8mKQGTHkoRfT9nGE7Y5012QPVyQPlWTJ04bIKTKez_jwI8jAEmCOvxBg-xIb387yHNu0V-vs47bDLu0/s400/Screen+Shot+2017-07-15+at+4.07.10+PM.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Setelah aplikasi di daftarkan di firebase console, kemudian kita masuk ke project baru yang sudah dibuat.&lt;br /&gt;
&lt;br /&gt;
Buka &lt;b&gt;build.gradle&lt;/b&gt; pada bagian &lt;b&gt;&lt;i&gt;Top-Level&lt;/i&gt;&lt;/b&gt; dan tambahkan dependencies berikut.
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
dependencies {
    ...
    classpath 'com.google.gms:google-services:3.1.0'
    // NOTE: Do not place your application dependencies here; they belong
    // in the individual module build.gradle files
}
&lt;/code&gt;
&lt;/pre&gt;
Lalu &lt;b&gt;build.gradle&lt;/b&gt; pada bagian &lt;i&gt;&lt;b&gt;Module-Level&lt;/b&gt;&lt;/i&gt; tambahkan plugin dan library firebase.
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:25.0.1'
    compile 'com.google.firebase:firebase-messaging:11.0.2'
    testCompile 'junit:junit:4.12'
}
// Add to the bottom of the file
apply plugin: 'com.google.gms.google-services'
&lt;/code&gt;
&lt;/pre&gt;
Setelah itu re-build project.&lt;br /&gt;
&lt;br /&gt;
Jika agan menemukan &lt;b&gt;&lt;span style="color: red;"&gt;error&lt;/span&gt;&lt;/b&gt; di bawah, mungkin &lt;b&gt;Google Repository&lt;/b&gt; agan belum di update. Silahkan buka &lt;b&gt;SDK Manager&lt;/b&gt; lalu update Google Repository.

&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIFJXmz-h9Glyb3-4Jxxk_EGRRorLbPQdIwT1ccFlVkUsG77tQEWLpgfgMMwrw5iklpDUbBbf_mFrMib-rqten31tNlcX-j4vvUe8IqyZh0rS2ZKlfhIA6S0eicEB38aGdHms0801SQoE/s1600/Screen+Shot+2017-07-15+at+4.17.12+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="998" data-original-width="1398" height="285" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIFJXmz-h9Glyb3-4Jxxk_EGRRorLbPQdIwT1ccFlVkUsG77tQEWLpgfgMMwrw5iklpDUbBbf_mFrMib-rqten31tNlcX-j4vvUe8IqyZh0rS2ZKlfhIA6S0eicEB38aGdHms0801SQoE/s400/Screen+Shot+2017-07-15+at+4.17.12+PM.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Sampai di sini kita lanjut ke bagian &lt;b&gt;desain layout&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
Buat layout dengan nama &lt;b&gt;activity_main.xml&lt;/b&gt; lalu tambahkan kode berikut :
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context="id.co.blogspot.wimsonevel.android_pushnotification.MainActivity"&amp;gt;

    &amp;lt;ImageView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:src="@drawable/firebase_lockup_400"
        tools:ignore="ContentDescription" /&amp;gt;

    &amp;lt;Switch
        android:id="@+id/switchNews"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="16dp"
        android:gravity="start"
        android:checked="false"
        android:text="@string/news"/&amp;gt;

    &amp;lt;Switch
        android:id="@+id/switchPromo"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="16dp"
        android:gravity="start"
        android:checked="false"
        android:text="@string/promo" /&amp;gt;

    &amp;lt;Button
        android:id="@+id/btn_token"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        android:text="@string/show_token"/&amp;gt;

    &amp;lt;TextView
        android:id="@+id/tv_token"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="16dp" /&amp;gt;

&amp;lt;/LinearLayout&amp;gt;
&lt;/code&gt;
&lt;/pre&gt;
Dan beberapa resources lainnya.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;strings.xml
&lt;/b&gt;&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
&amp;lt;resources&amp;gt;
    &amp;lt;string name="app_name"&amp;gt;Android-PushNotification&amp;lt;/string&amp;gt;

    &amp;lt;string name="token"&amp;gt;Token : %s&amp;lt;/string&amp;gt;
    &amp;lt;string name="news"&amp;gt;News&amp;lt;/string&amp;gt;
    &amp;lt;string name="promo"&amp;gt;Promo&amp;lt;/string&amp;gt;
    &amp;lt;string name="show_token"&amp;gt;Show Token&amp;lt;/string&amp;gt;

&amp;lt;/resources&amp;gt;
&lt;/code&gt;
&lt;/pre&gt;
&lt;b&gt;colors.xml
&lt;/b&gt;&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;resources&amp;gt;
    &amp;lt;color name="colorPrimary"&amp;gt;#FFCC01&amp;lt;/color&amp;gt;
    &amp;lt;color name="colorPrimaryDark"&amp;gt;#FFA701&amp;lt;/color&amp;gt;
    &amp;lt;color name="colorAccent"&amp;gt;#FF4081&amp;lt;/color&amp;gt;
&amp;lt;/resources&amp;gt;
&lt;/code&gt;
&lt;/pre&gt;
Selanjutnya kita masuk ke bagian coding java-nya. Buat kelas-kelas java di bawah ini : &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;MyFirebaseInstanceIDService.java
&lt;/b&gt;&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
import android.util.Log;

import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService;

/**
 * Created by Wim on 7/15/17.
 */

public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {

    private static final String TAG = "MyFirebaseIIDService";

    @Override
    public void onTokenRefresh() {
        // Get updated InstanceID token.
        String refreshedToken = FirebaseInstanceId.getInstance().getToken();
        Log.d(TAG, "Refreshed token: " + refreshedToken);

        // If you want to send messages to this application instance or
        // manage this apps subscriptions on the server side, send the
        // Instance ID token to your app server.
        sendRegistrationToServer(refreshedToken);
    }

    private void sendRegistrationToServer(String token) {
        // TODO: Implement this method to send token to your app server.
    }

}
&lt;/code&gt;
&lt;/pre&gt;
Kelas ini merupakan firebase service untuk mendapatkan &lt;b&gt;token&lt;/b&gt; unik yang selalu diupdate.  Nah, token inilah nantinya yang akan membedakan device satu dengan device lainnya.&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;b&gt;MyFirebaseMessagingService.java
&lt;/b&gt;&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.media.RingtoneManager;
import android.net.Uri;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;

/**
 * Created by Wim on 7/15/17.
 */

public class MyFirebaseMessagingService extends FirebaseMessagingService {

    private static final String TAG = "MyFirebaseMsgService";

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {

        // TODO(developer): Handle FCM messages here.
        Log.d(TAG, "From: " + remoteMessage.getFrom());

        // Check if message contains a data payload.
        if (remoteMessage.getData().size() &amp;gt; 0) {
            Log.d(TAG, "Message data payload: " + remoteMessage.getData());

        }

        // Check if message contains a notification payload.
        if (remoteMessage.getNotification() != null) {
            Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
            sendNotification(remoteMessage.getNotification().getBody());
        }

    }

    private void sendNotification(String messageBody) {
        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent,
                PendingIntent.FLAG_ONE_SHOT);

        Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("FCM Message")
                .setContentText(messageBody)
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);

        NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        notificationManager.notify(0, notificationBuilder.build());
    }

}
&lt;/code&gt;
&lt;/pre&gt;
Kelas ini berfungsi untuk menerima message dari push notification. Message diterima melalui method &lt;b&gt;onMessageReceived(RemoteMessage remoteMessage)&lt;/b&gt;. &lt;br /&gt;
&lt;br /&gt;
Lanjutkan dengan membuat kelas activity dengan nama &lt;b&gt;MainActivity.java&lt;/b&gt;
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;

import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.messaging.FirebaseMessaging;

public class MainActivity extends AppCompatActivity {

    private static final String PREF_SWITCH_NEWS = "switch_news";
    private static final String PREF_SWITCH_PROMO = "switch_promo";

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


        Switch switchNews = (Switch) findViewById(R.id.switchNews);
        Switch switchPromo = (Switch) findViewById(R.id.switchPromo);
        Button btnToken = (Button) findViewById(R.id.btn_token);

        btnToken.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String token = FirebaseInstanceId.getInstance().getToken();
                TextView tvToken = (TextView) findViewById(R.id.tv_token);
                tvToken.setText(getResources().getString(R.string.token, token));

                Log.i("TOKEN", token);
            }
        });

        switchNews.setChecked(isSwitchChecked(PREF_SWITCH_NEWS));
        switchPromo.setChecked(isSwitchChecked(PREF_SWITCH_PROMO));

        switchNews.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
                setSwitchChecked(PREF_SWITCH_NEWS, checked);

                if(checked) {
                    FirebaseMessaging.getInstance().subscribeToTopic("news");
                    Toast.makeText(getApplicationContext(), "Subscribe to News Topic" , Toast.LENGTH_SHORT).show();
                }else{
                    FirebaseMessaging.getInstance().unsubscribeFromTopic("news");
                    Toast.makeText(getApplicationContext(), "Unsubscribe from News Topic" , Toast.LENGTH_SHORT).show();
                }

            }
        });

        switchPromo.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
                setSwitchChecked(PREF_SWITCH_PROMO, checked);

                if(checked) {
                    FirebaseMessaging.getInstance().subscribeToTopic("promo");
                    Toast.makeText(getApplicationContext(), "Subscribe to Promo Topic", Toast.LENGTH_SHORT).show();
                }else{
                    FirebaseMessaging.getInstance().unsubscribeFromTopic("promo");
                    Toast.makeText(getApplicationContext(), "Unsubscribe from Promo Topic", Toast.LENGTH_SHORT).show();
                }

            }
        });
    }

    private void setSwitchChecked(String permission, boolean isChecked) {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
        SharedPreferences.Editor editor = preferences.edit();
        editor.putBoolean(permission, isChecked);
        editor.apply();
    }

    private boolean isSwitchChecked(String permission) {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
        return preferences.getBoolean(permission, false);
    }
}
&lt;/code&gt;
&lt;/pre&gt;
Pada kode di atas, untuk men-&lt;b&gt;subscibe&lt;/b&gt; atau men-&lt;b&gt;unsubscribe&lt;/b&gt; ke topik yang diinginkan tinggal memanggil method :
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
FirebaseMessaging.getInstance().subscribeToTopic("news");

FirebaseMessaging.getInstance().unsubscribeFromTopic("news");
&lt;/code&gt;
&lt;/pre&gt;
Terakhir, tambahkan service di &lt;b&gt;AndroidManifest.xml&lt;/b&gt;
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="id.co.blogspot.wimsonevel.android_pushnotification"&amp;gt;

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

                &amp;lt;category android:name="android.intent.category.LAUNCHER" /&amp;gt;
            &amp;lt;/intent-filter&amp;gt;
        &amp;lt;/activity&amp;gt;

        &amp;lt;!-- [START fcm_default_icon] --&amp;gt;
        &amp;lt;!-- Set custom default icon. This is used when no icon is set for incoming notification messages.
             See README(https://goo.gl/l4GJaQ) for more. --&amp;gt;
        &amp;lt;meta-data
            android:name="com.google.firebase.messaging.default_notification_icon"
            android:resource="@mipmap/ic_launcher" /&amp;gt;
        &amp;lt;!-- Set color used with incoming notification messages. This is used when no color is set for the incoming
             notification message. See README(https://goo.gl/6BKBk7) for more. --&amp;gt;
        &amp;lt;meta-data
            android:name="com.google.firebase.messaging.default_notification_color"
            android:resource="@color/colorAccent" /&amp;gt;
        &amp;lt;!-- [END fcm_default_icon] --&amp;gt;

        &amp;lt;!-- [START firebase_service] --&amp;gt;
        &amp;lt;service
            android:name=".MyFirebaseMessagingService"&amp;gt;
            &amp;lt;intent-filter&amp;gt;
                &amp;lt;action android:name="com.google.firebase.MESSAGING_EVENT"/&amp;gt;
            &amp;lt;/intent-filter&amp;gt;
        &amp;lt;/service&amp;gt;
        &amp;lt;!-- [END firebase_service] --&amp;gt;
        &amp;lt;!-- [START firebase_iid_service] --&amp;gt;
        &amp;lt;service
            android:name=".MyFirebaseInstanceIDService"&amp;gt;
            &amp;lt;intent-filter&amp;gt;
                &amp;lt;action android:name="com.google.firebase.INSTANCE_ID_EVENT"/&amp;gt;
            &amp;lt;/intent-filter&amp;gt;
        &amp;lt;/service&amp;gt;
        &amp;lt;!-- [END firebase_iid_service] --&amp;gt;

    &amp;lt;/application&amp;gt;

&amp;lt;/manifest&amp;gt;
&lt;/code&gt;
&lt;/pre&gt;
Build dan jalankan maka tampilannya seperti berikut.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgydMicYcKuxdRbFXB-4FrwyvAZ-rmu-4GcGvEwBeCqFWYxQGvQpojiiHvCvKoXbIxvqqbG_GENLO9NDPDgf3_L-KnB6MIu58fMuv9Haf9p9WbGOfseSzwXKD2Bo2L0GQfmNp3uheVS024/s1600/Screenshot_1500204268.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="1600" data-original-width="900" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgydMicYcKuxdRbFXB-4FrwyvAZ-rmu-4GcGvEwBeCqFWYxQGvQpojiiHvCvKoXbIxvqqbG_GENLO9NDPDgf3_L-KnB6MIu58fMuv9Haf9p9WbGOfseSzwXKD2Bo2L0GQfmNp3uheVS024/s400/Screenshot_1500204268.png" width="225" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Push Notification melalui Firebase Console&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Sekarang kita akan coba mengirimkan push notification dari firebase console.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrG-gB8R4ip92dNY8BHFXL26Cn8Ns8KPAQg6qs_FXKkVRP_HHeEPhhgfYhTHRDB_Tas-1tO6yMxKdciHuZPMfhQJZ8vZIk52XLLUE40BhMx0UrqFkHRrf1bysQgO0Sryb3axDQVdsB668/s1600/Screen+Shot+2017-07-19+at+2.56.40+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="981" data-original-width="1600" height="392" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrG-gB8R4ip92dNY8BHFXL26Cn8Ns8KPAQg6qs_FXKkVRP_HHeEPhhgfYhTHRDB_Tas-1tO6yMxKdciHuZPMfhQJZ8vZIk52XLLUE40BhMx0UrqFkHRrf1bysQgO0Sryb3axDQVdsB668/s640/Screen+Shot+2017-07-19+at+2.56.40+PM.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Klik &lt;b&gt;Send Message&lt;/b&gt;, di aplikasi langsung menerima push notification. &lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-oew7IsUMQnhKz8E5lgTrfQnrewO4Cdin2DxvXphSr-itKnw_fbHZrDTLLABe8sxVG4nvFEoR6CtIqE_5lTCHTJ4FpEMv9U5skH94CGr9jo4QrZOwRhtF61uNEapU9NQYbmmQ2nwWFG8/s1600/Screenshot_1500451170.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="1600" data-original-width="900" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-oew7IsUMQnhKz8E5lgTrfQnrewO4Cdin2DxvXphSr-itKnw_fbHZrDTLLABe8sxVG4nvFEoR6CtIqE_5lTCHTJ4FpEMv9U5skH94CGr9jo4QrZOwRhtF61uNEapU9NQYbmmQ2nwWFG8/s400/Screenshot_1500451170.png" width="225" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Lalu kita tes juga mengirim push notification ke topik news.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhyphenhyphendG5M2kg6Rouo2smDrJ1U5Vq-LDCrex79koCa31EDP3HY8mrgGu8Ps3dOwOezMN1t3d7Biq801yW3t8AEtnP3XmJzZQB11A5iu0TgxgI9hA6jwwBW2pbC27jUVo6VNjlFQME-AAn7Ik/s1600/Screen+Shot+2017-07-19+at+3.02.55+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="978" data-original-width="1600" height="390" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhyphenhyphendG5M2kg6Rouo2smDrJ1U5Vq-LDCrex79koCa31EDP3HY8mrgGu8Ps3dOwOezMN1t3d7Biq801yW3t8AEtnP3XmJzZQB11A5iu0TgxgI9hA6jwwBW2pbC27jUVo6VNjlFQME-AAn7Ik/s640/Screen+Shot+2017-07-19+at+3.02.55+PM.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Pada aplikasi, aktifkan pemberitahuan news maka akan mendapatkan push notification di topik news.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCuzFlVPOwqbzSeAQBuTDQgbcUycWKrGQyd3RpdR6nosxwmefPj4UmVs5ORVZY6DYcejIoMr73xsp4AC56aILRJb0sQbyMCtM_96B40kOtdCGhHE90L6Ay5EqCSeg8D_WsKNn_-skUlQQ/s1600/Screenshot_1500451529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="1600" data-original-width="900" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCuzFlVPOwqbzSeAQBuTDQgbcUycWKrGQyd3RpdR6nosxwmefPj4UmVs5ORVZY6DYcejIoMr73xsp4AC56aILRJb0sQbyMCtM_96B40kOtdCGhHE90L6Ay5EqCSeg8D_WsKNn_-skUlQQ/s400/Screenshot_1500451529.png" width="225" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Push Notification melalui backend PHP&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Selain dari firebase console kita juga dapat mengirimkan push notification dari &lt;b&gt;PHP&lt;/b&gt;. Di sini yang dibutuhkan adalah alamat &lt;b&gt;url&lt;/b&gt; dan &lt;b&gt;server key&lt;/b&gt;. Untuk melihat server key bisa dilihat di menu firebase console bagian settings.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrB9W4_OC-pmCXBXvO2xgobCoShFzKmqVTaO6DDWJUNao_o1NX1jYQK4vyqjvN2wHo2SOFKXLcaShzWgqZ9lAOiS5lfm0SrdxuEdWQ_wvhDHFT07Y-j5ngr5BPXjLQOtc-G1AtiZGVA0w/s1600/Screen+Shot+2017-07-19+at+4.17.15+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="528" data-original-width="1600" height="208" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrB9W4_OC-pmCXBXvO2xgobCoShFzKmqVTaO6DDWJUNao_o1NX1jYQK4vyqjvN2wHo2SOFKXLcaShzWgqZ9lAOiS5lfm0SrdxuEdWQ_wvhDHFT07Y-j5ngr5BPXjLQOtc-G1AtiZGVA0w/s640/Screen+Shot+2017-07-19+at+4.17.15+PM.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Copy Server key agan, kemudian buat kode php berikut :&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;index.php
&lt;/b&gt;
&lt;br /&gt;
&lt;pre style="background-color: #F3F3F3; color: #616161;"&gt;
&lt;code style="white-space: pre; display: block; background-color: #F3F3F3;"&gt;
&amp;lt;html&amp;gt;
    &amp;lt;head&amp;gt;
        &amp;lt;title&amp;gt;Firebase Cloud Messaging&amp;lt;/title&amp;gt;
        &amp;lt;meta charset="UTF-8"&amp;gt;
        &amp;lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&amp;gt;

        &amp;lt;style&amp;gt;
            input[type=text], select {
                width: 100%;
                padding: 12px 20px;
                margin: 8px 0;
                display: inline-block;
                border: 1px solid #ccc;
                border-radius: 4px;
                box-sizing: border-box;
            }

            input[type=submit] {
                background-color: #4CAF50;
                color: white;
                padding: 14px 20px;
                margin: 8px 0;
                border: none;
                border-radius: 4px;
                cursor: pointer;
            }

            input[type=submit]:hover {
                background-color: #45a049;
            }

        &amp;lt;/style&amp;gt;
        
    &amp;lt;/head&amp;gt;
    &amp;lt;body&amp;gt;
        &amp;lt;h3&amp;gt;Firebase Cloud Messaging&amp;lt;/h3&amp;gt;

        &amp;lt;div&amp;gt;
          &amp;lt;form action="index.php" method="get"&amp;gt;
            &amp;lt;label for="token"&amp;gt;FCM Registration Token&amp;lt;/label&amp;gt;
            &amp;lt;input type="text" id="token" name="token" placeholder="Input Token"&amp;gt;

            &amp;lt;label for="message"&amp;gt;Message&amp;lt;/label&amp;gt;
            &amp;lt;input type="text" id="message" name="message" placeholder="Input Message"&amp;gt;
            
            &amp;lt;input type="hidden" name="type" value="single" &amp;gt;
            &amp;lt;input type="submit" value="Kirim"&amp;gt;
          &amp;lt;/form&amp;gt;
            
            
          &amp;lt;form action="index.php"&amp;gt;
            &amp;lt;label for="fname"&amp;gt;Topics&amp;lt;/label&amp;gt;
              
            &amp;lt;select name="topics"&amp;gt;
              &amp;lt;option value="news"&amp;gt;News&amp;lt;/option&amp;gt;
              &amp;lt;option value="promo"&amp;gt;Promo&amp;lt;/option&amp;gt;
            &amp;lt;/select&amp;gt;

            &amp;lt;label for="lname"&amp;gt;Message&amp;lt;/label&amp;gt;
            &amp;lt;input type="text" id="message" name="message" placeholder="Input Message"&amp;gt;
              
            &amp;lt;input type="hidden" name="type" value="topics" &amp;gt;
            &amp;lt;input type="submit" value="Kirim"&amp;gt;
          &amp;lt;/form&amp;gt;
            
        &amp;lt;/div&amp;gt;

        &amp;lt;?php
        // Enabling error reporting
        error_reporting(-1);
        ini_set('display_errors', 'On');
 
        $type = isset($_GET['type']) ? $_GET['type'] : '';
        
        $fields = NULL;
        
        if($type == "single") {
            $token = isset($_GET['token']) ? $_GET['token'] : '';
            $message = isset($_GET['message']) ? $_GET['message'] : '';
            
            $res = array();
            $res['body'] = $message;
            
            $fields = array(
                'to' =&amp;gt; $token,
                'notification' =&amp;gt; $res,
            );
        
            echo 'FCM Reg Id : '. $token . '&amp;lt;br/&amp;gt;Message : ' . $message;
        }else if($type == "topics") {
            $topics = isset($_GET['topics']) ? $_GET['topics'] : '';
            $message = isset($_GET['message']) ? $_GET['message'] : '';
            
            $res = array();
            $res['body'] = $message;
            
            $fields = array(
                'to' =&amp;gt; '/topics/' . $topics,
                'notification' =&amp;gt; $res,
            );
            
            echo json_encode($fields);
            echo 'Topics : '. $topics . '&amp;lt;br/&amp;gt;Message : ' . $message;
        }
        
        // Set POST variables
        $url = 'https://fcm.googleapis.com/fcm/send';
        $server_key = "SERVER KEY AGAN";
        
        $headers = array(
            'Authorization: key=' . $server_key,
            'Content-Type: application/json'
        );
        // Open connection
        $ch = curl_init();
 
        // Set the url, number of POST vars, POST data
        curl_setopt($ch, CURLOPT_URL, $url);
 
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
 
        // Disabling SSL Certificate support temporarly
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
 
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
 
        // Execute post
        $result = curl_exec($ch);
        if ($result === FALSE) {
            echo 'Curl failed: ' . curl_error($ch);
        }
 
        // Close connection
        curl_close($ch);
               
        ?&amp;gt;
        
    &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;
&lt;/pre&gt;
Sekarang silahkan agan coba mengirim push notification. (&lt;b&gt;Tested : 100% work&lt;/b&gt;)&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKVTs4sYS_BdMZRlQlvF9OWSu2V0URGr4JV8y9UucHFygDwiPoagvt9HpDgeu6WK1flxYTBjmPo-n1OOhn6XFeVrYUD6Srz6XPtErHwRnlP_SZ5tKzTh7Te0WXRu1VHyOeJX86mCYCGR4/s1600/Screen+Shot+2017-07-19+at+4.15.13+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="704" data-original-width="1600" height="280" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKVTs4sYS_BdMZRlQlvF9OWSu2V0URGr4JV8y9UucHFygDwiPoagvt9HpDgeu6WK1flxYTBjmPo-n1OOhn6XFeVrYUD6Srz6XPtErHwRnlP_SZ5tKzTh7Te0WXRu1VHyOeJX86mCYCGR4/s640/Screen+Shot+2017-07-19+at+4.15.13+PM.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Jika ingin mempelajari lebih lanjut silahkan lihat di dokumentasinya di &lt;a href="https://firebase.google.com/docs/"&gt;https://firebase.google.com/docs/&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Source code lengkap dapat dilihat di &lt;a href="https://github.com/wimsonevel/Android-PushNotification"&gt;https://github.com/wimsonevel/Android-PushNotification&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Sekian dulu tutorial kali ini semoga bermanfaat.&lt;br /&gt;
Don’t forget to share, thanks :)</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7EU1Zsbj5JHJ_8jtNP430Sg2E3rQSZfRo_jZ3EB3XZ4PQ4tpnMyL792oTH4pSSCwZySitv9uGc6_ggTBkmQCq8zJwkpBFlfrQ-Ce6GbZElWPHiV2N7wAbrR8hjMh6fyH9VGoPBl_mNuU/s72-c/android_fcm.png" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">35</thr:total></item><item><title>Discover Movie Apps</title><link>http://wimsonevel.blogspot.com/2017/07/discover-movie-apps.html</link><category>Open Source</category><author>noreply@blogger.com (Wim Sonevel)</author><pubDate>Sat, 15 Jul 2017 15:40:00 +0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-6966757688576433754.post-3846583375139677689</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiemk88J_gFy94kgH_4iV9xR9x87q7UqtefOzwik6DN5IjnsM1r7jh4cqtly4RNSzrxFYZqYq1AIu_XwZsnIUi6qqZtTuZkq1F0QXq17dWdRkYmuQJyLaAZnonRhzA4Qbs5YXOBobKUwjY/s1600/discover_movie_apps.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="800" data-original-width="1280" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiemk88J_gFy94kgH_4iV9xR9x87q7UqtefOzwik6DN5IjnsM1r7jh4cqtly4RNSzrxFYZqYq1AIu_XwZsnIUi6qqZtTuZkq1F0QXq17dWdRkYmuQJyLaAZnonRhzA4Qbs5YXOBobKUwjY/s640/discover_movie_apps.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Aplikasi untuk mencari dan menemukan informasi dari film-film hollywood terpopuler. Data-data film bersumber dari &lt;b&gt;The Movie Database&lt;/b&gt; (&lt;b&gt;TMDb&lt;/b&gt;), bisa dilihat juga websitenya &lt;a href="https://www.themoviedb.org/"&gt;https://www.themoviedb.org/&lt;/a&gt;.  &lt;b&gt;TMDb&lt;/b&gt; menyediakan &lt;b&gt;API Publi&lt;/b&gt;c yang dapat digunakan oleh siapa saja untuk mengakses data-data film di dalamnya. So, sejauh ini saya sudah membuat aplikasi berikut yang bisa dikatakan masih sederhana hehehe..&lt;br /&gt;
&lt;br /&gt;
Tampilannya kurang lebih seperti di bawah ini.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvFiAaGP7IvNHjPQjAd4hqnl0gtl0sS1OADQhBv0mK-eot-AKdp1LRXb0rQyx9GRKPPfqD1Ar06yArBIwEE6rTH8i2op8EPdYFj1wx162Uj6h8mTAcHe4xlKnpOPzqmJOOC5H4xZeKFfU/s1600/ss_movie_apps.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="1422" data-original-width="1600" height="355" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvFiAaGP7IvNHjPQjAd4hqnl0gtl0sS1OADQhBv0mK-eot-AKdp1LRXb0rQyx9GRKPPfqD1Ar06yArBIwEE6rTH8i2op8EPdYFj1wx162Uj6h8mTAcHe4xlKnpOPzqmJOOC5H4xZeKFfU/s400/ss_movie_apps.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
&lt;br /&gt;
Apabila teman-teman tertarik untuk mengoprek, mengutak-atik atau mengembangkan project ini lebih lanjut saya persilahkan langsung aja download atau clone projectnya di github saya.&lt;br /&gt;
&lt;a href="https://github.com/wimsonevel/Android-MovieDB"&gt;https://github.com/wimsonevel/Android-MovieDB&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Jangan lupa fork dan kasih bintang ya gan :D&lt;br /&gt;
Thanks semoga bermanfaat.</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiemk88J_gFy94kgH_4iV9xR9x87q7UqtefOzwik6DN5IjnsM1r7jh4cqtly4RNSzrxFYZqYq1AIu_XwZsnIUi6qqZtTuZkq1F0QXq17dWdRkYmuQJyLaAZnonRhzA4Qbs5YXOBobKUwjY/s72-c/discover_movie_apps.png" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>Request Tutorial</title><link>http://wimsonevel.blogspot.com/2017/07/request-tutorial.html</link><author>noreply@blogger.com (Wim Sonevel)</author><pubDate>Thu, 13 Jul 2017 12:26:00 +0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-6966757688576433754.post-2225146253269409442</guid><description>Halo agan-agan sekalian, pada kesempatan kali ini saya akan mencoba membuat tutorial pemrograman langsung dari request agan-agan sekalian. Tutorialnya bisa seputar pemrograman Java, Android dan iOS. Bagi agan-agan yang ingin request silahkan tinggalkan jejak di bawah ini. Thanks :)&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;*Lamanya pembuatan tutorial tergantung dari mood :'v (biasanya 1-3 minggu bahkan lebih)&amp;nbsp;&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;*Request yang masuh saya list dulu (tidak ada jaminan akan dibikinin, tpi sy usahakan)&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;*Harap maklum&lt;/b&gt;</description><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">30</thr:total></item><item><title>RE : (Tutorial Android) HTTP Client on Android with Retrofit</title><link>http://wimsonevel.blogspot.com/2017/07/re-tutorial-android-http-client-on.html</link><category>Android</category><author>noreply@blogger.com (Wim Sonevel)</author><pubDate>Wed, 5 Jul 2017 18:45:00 +0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-6966757688576433754.post-4149928769520353060</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_yloCLtdnGMuezr83jzkkgbKnQDr5s9qc-sMfDCy9pd07J9EyySY-Hk1uqwVfDCBNZoBXJTia2hG7jv2a_IoEsbev194dzwNOhSodlcC94CaYdAzvjG9Znxl5Fp05Yju2t68g9sr14iQ/s1600/android_retrofit.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="800" data-original-width="1280" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_yloCLtdnGMuezr83jzkkgbKnQDr5s9qc-sMfDCy9pd07J9EyySY-Hk1uqwVfDCBNZoBXJTia2hG7jv2a_IoEsbev194dzwNOhSodlcC94CaYdAzvjG9Znxl5Fp05Yju2t68g9sr14iQ/s640/android_retrofit.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Halo semua bagaimana kabarnya?&lt;br /&gt;
&lt;br /&gt;
Pada artikel kali ini saya ingin membahas ulang tutorial Retrofit. Sesuai janji saya memposting ini dikarenakan project dari artikel sebelumnya &lt;a href="http://wimsonevel.blogspot.co.id/2016/07/tutorial-android-http-client-on-android.html"&gt;http://wimsonevel.blogspot.co.id/2016/07/tutorial-android-http-client-on-android.html&lt;/a&gt;&amp;nbsp;tidak dapat berfungsi dengan baik. Maka dari itu saya akan membuat ulang project menggunakan Retrofit namun dengan studi kasus yang berbeda.&lt;br /&gt;
&lt;br /&gt;
Pada project kali ini kita menggunakan &lt;b&gt;Free API Database Movie&lt;/b&gt; di &lt;a href="https://www.themoviedb.org/"&gt;https://www.themoviedb.org&lt;/a&gt;. Untuk mengakses API-nya diperlukan &lt;b&gt;API key&lt;/b&gt;, terlebih dahulu harus buat akun. Setelah itu akses ke menu settings di profile, kemudian generate API key di menu API.&lt;br /&gt;
&lt;br /&gt;
Dokumentasi API lengkapnya bisa di &lt;a href="https://developers.themoviedb.org/3"&gt;https://developers.themoviedb.org/3&lt;/a&gt;&lt;br /&gt;
&lt;b&gt;Note&lt;/b&gt;: API yang kita gunakan versi 3&lt;br /&gt;
&lt;br /&gt;
Beberapa API yang akan kita pakai diantaranya :&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;1. Popular Movies
&lt;/b&gt;&lt;br /&gt;
Untuk requestnya bisa dilihat di &lt;a href="https://developers.themoviedb.org/3/movies/get-popular-movies"&gt;https://developers.themoviedb.org/3/movies/get-popular-movies&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Responsenya :&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;{
  "page": 1,
  "total_results": 19587,
  "total_pages": 980,
  "results": [
    {
      "vote_count": 3593,
      "id": 321612,
      "video": false,
      "vote_average": 6.8,
      "title": "Beauty and the Beast",
      "popularity": 257.04688,
      "poster_path": "/tWqifoYuwLETmmasnGHO7xBjEtt.jpg",
      "original_language": "en",
      "original_title": "Beauty and the Beast",
      "genre_ids": [
        10751,
        14,
        10749
      ],
      "backdrop_path": "/6aUWe0GSl69wMTSWWexsorMIvwU.jpg",
      "adult": false,
      "overview": "A live-action adaptation of Disney's version of the classic 'Beauty and the Beast' tale of a cursed prince and a beautiful young woman who helps him break the spell.",
      "release_date": "2017-03-16"
    },

    ...

  ]
}
&lt;/pre&gt;
&lt;b&gt;2. Movie Detai&lt;/b&gt;l&lt;br /&gt;
Untuk requestnya bisa dilihat di &lt;a href="https://developers.themoviedb.org/3/movies/get-movie-details"&gt;https://developers.themoviedb.org/3/movies/get-movie-details&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Responsenya :&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;{
  "adult": false,
  "backdrop_path": "/hA5oCgvgCxj5MEWcLpjXXTwEANF.jpg",
  "belongs_to_collection": null,
  "budget": 120000000,
  "genres": [
    {
      "id": 28,
      "name": "Action"
    },
    {
      "id": 12,
      "name": "Adventure"
    },
    {
      "id": 14,
      "name": "Fantasy"
    },
    {
      "id": 878,
      "name": "Science Fiction"
    }
  ],
  "homepage": "http://www.warnerbros.com/wonder-woman",
  "id": 297762,
  "imdb_id": "tt0451279",
  "original_language": "en",
  "original_title": "Wonder Woman",
  "overview": "An Amazon princess comes to the world of Man to become the greatest of the female superheroes.",
  "popularity": 236.48453,
  "poster_path": "/imekS7f1OuHyUP2LAiTEM0zBzUz.jpg",
  "production_companies": [
    {
      "name": "Dune Entertainment",
      "id": 444
    },
    {
      "name": "Atlas Entertainment",
      "id": 507
    },
    {
      "name": "Warner Bros.",
      "id": 6194
    },
    {
      "name": "DC Entertainment",
      "id": 9993
    },
    {
      "name": "Cruel &amp;amp; Unusual Films",
      "id": 9995
    },
    {
      "name": "TENCENT PICTURES",
      "id": 81620
    },
    {
      "name": "Wanda Pictures",
      "id": 83838
    }
  ],
  "production_countries": [
    {
      "iso_3166_1": "US",
      "name": "United States of America"
    }
  ],
  "release_date": "2017-05-30",
  "revenue": 573495580,
  "runtime": 141,
  "spoken_languages": [
    {
      "iso_639_1": "de",
      "name": "Deutsch"
    },
    {
      "iso_639_1": "en",
      "name": "English"
    }
  ],
  "status": "Released",
  "tagline": "Power. Grace. Wisdom. Wonder.",
  "title": "Wonder Woman",
  "video": false,
  "vote_average": 7,
  "vote_count": 2225
}
&lt;/pre&gt;
&lt;b&gt;3. Trailer&lt;/b&gt;&lt;br /&gt;
Untuk requestnya bisa dilihat di &lt;a href="https://developers.themoviedb.org/3/movies/get-movie-videos"&gt;https://developers.themoviedb.org/3/movies/get-movie-videos&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Responsenya :&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;{
  "id": 297762,
  "results": [
    {
      "id": "58ba5869925141609e01849f",
      "iso_639_1": "en",
      "iso_3166_1": "US",
      "key": "5lGoQhFb4NM",
      "name": "Official Comic-Con Trailer",
      "site": "YouTube",
      "size": 1080,
      "type": "Trailer"
    },

...

  ]
}
&lt;/pre&gt;
&lt;b&gt;4. Review&lt;/b&gt;&lt;br /&gt;
Untuk requestnya bisa dilihat di &lt;a href="https://developers.themoviedb.org/3/movies/get-movie-reviews"&gt;https://developers.themoviedb.org/3/movies/get-movie-reviews&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Responsenya :&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;{
  "id": 297762,
  "page": 1,
  "results": [
    {
      "id": "59303b4c92514166e9000f76",
      "author": "Gimly",
      "content": "I'd just like to thank Patty Jenkins for making a DCIThoughtSheWasWithUniverse movie that wasn't fucking garbage.\r\n\r\nIf I'm being completely honest, the two people I went to the cinema to watch _Wonder Woman_ with and I did spend the next two hours after coming out of our screening discussing the various problems with the movie, but we also all agreed on one thing: We still loved it.\r\n\r\nMaybe it's just the rose-coloured glasses of comparison, but I had an excellent time with _Wonder Woman_, and I'm excited to go back to the cinema and watch it, at least one more time.\r\n\r\nIt's the first time I've said that about a DC movie since _The Dark Knight Rises_.\r\n\r\n_Final rating:★★★½ - I strongly recommend you make the time._",
      "url": "https://www.themoviedb.org/review/59303b4c92514166e9000f76"
    },

  ...

  ],
  "total_pages": 1,
  "total_results": 3
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Buat Project Baru&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Buka Android Studio dan buat project baru dengan sistem package sebagai berikut :&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihRPIM3ju0tpaFvGHRylcfDHcs710r_bQRtoEoTurLMjMLa6yCvsrP4DHkn2aAI5d8m6Vb6RrDibvfr4UG-vAR6eO-7ED4V00bwrXyooX6UYYD45fTCVmHy0pqr59r51aeOiGhh8ZuJBo/s1600/Screen+Shot+2017-07-03+at+5.16.10+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="1168" data-original-width="626" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihRPIM3ju0tpaFvGHRylcfDHcs710r_bQRtoEoTurLMjMLa6yCvsrP4DHkn2aAI5d8m6Vb6RrDibvfr4UG-vAR6eO-7ED4V00bwrXyooX6UYYD45fTCVmHy0pqr59r51aeOiGhh8ZuJBo/s400/Screen+Shot+2017-07-03+at+5.16.10+PM.png" width="213" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;span id="goog_1243777859"&gt;&lt;/span&gt;&lt;span id="goog_1243777860"&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Buka gradle, kemudian tambahkan library &lt;b&gt;Retrofit 2&lt;/b&gt;. Latest version bisa dilihat di &lt;a href="http://square.github.io/retrofit/"&gt;http://square.github.io/retrofit/&lt;/a&gt;
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;compile 'com.squareup.retrofit2:retrofit:2.3.0'
&lt;/pre&gt;
Tambahkan library converter gson agar respon json dapat di-convert dengan gson.
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;compile 'com.squareup.retrofit2:converter-gson:2.3.0'
&lt;/pre&gt;
Tambahkan library logging untuk memonitor request dan response dari retrofit.
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;compile 'com.squareup.okhttp3:logging-interceptor:3.8.0'
&lt;/pre&gt;
Dan juga tambahkan library tambahan lainnya
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:25.0.1'
    compile 'com.android.support:recyclerview-v7:25.0.1'
    compile 'com.squareup.retrofit2:retrofit:2.3.0'
    compile 'com.squareup.retrofit2:converter-gson:2.3.0'
    compile 'com.squareup.okhttp3:logging-interceptor:3.8.0'
    compile 'com.squareup.picasso:picasso:2.5.2'
    testCompile 'junit:junit:4.12'
}
&lt;/pre&gt;
&lt;br /&gt;
Letakkan &lt;b&gt;URL&lt;/b&gt; dan &lt;b&gt;API&lt;/b&gt; KEY di gradle.properties
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;BASE_URL = "https://api.themoviedb.org"
MOVIE_API_KEY = "YOUR API KEY"
IMG_URL = "http://image.tmdb.org/t/p/w185"
&lt;/pre&gt;
Letakkan konfigurasi &lt;b&gt;URL&lt;/b&gt; dan API &lt;b&gt;KEY&lt;/b&gt; di gradle
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    defaultConfig {
        applicationId "id.co.blogspot.wimsonevel.android_moviedb"
        minSdkVersion 16
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    buildTypes.each {
        it.buildConfigField 'String', 'BASE_URL', BASE_URL
        it.buildConfigField 'String', 'IMG_URL', IMG_URL
        it.buildConfigField 'String', 'MOVIE_API_KEY', MOVIE_API_KEY
    }
}
&lt;/pre&gt;
&lt;br /&gt;
Kemudian tambahkan resources yang diperlukan di folder res.&lt;br /&gt;
&lt;br /&gt;
values/strings.xml
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;resources&amp;gt;
    &amp;lt;string name="app_name"&amp;gt;Movie DB&amp;lt;/string&amp;gt;
    &amp;lt;string name="most_popular"&amp;gt;Most Popular&amp;lt;/string&amp;gt;
    &amp;lt;string name="movie_detail"&amp;gt;Movie Detail&amp;lt;/string&amp;gt;
    &amp;lt;string name="release_date"&amp;gt;Release Date&amp;lt;/string&amp;gt;
    &amp;lt;string name="duration"&amp;gt;Duration&amp;lt;/string&amp;gt;
    &amp;lt;string name="genre"&amp;gt;Genre&amp;lt;/string&amp;gt;
    &amp;lt;string name="homepage"&amp;gt;Homepage&amp;lt;/string&amp;gt;
    &amp;lt;string name="overview"&amp;gt;Overview&amp;lt;/string&amp;gt;
    &amp;lt;string name="trailers"&amp;gt;Trailers&amp;lt;/string&amp;gt;
    &amp;lt;string name="reviews"&amp;gt;Reviews&amp;lt;/string&amp;gt;
    &amp;lt;string name="title"&amp;gt;Title&amp;lt;/string&amp;gt;
&amp;lt;/resources&amp;gt;
&lt;/pre&gt;
values/colors.xml
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;resources&amp;gt;
    &amp;lt;color name="colorPrimary"&amp;gt;#4CAF50&amp;lt;/color&amp;gt;
    &amp;lt;color name="colorPrimaryDark"&amp;gt;#43A047&amp;lt;/color&amp;gt;
    &amp;lt;color name="colorAccent"&amp;gt;#FF4081&amp;lt;/color&amp;gt;
    &amp;lt;color name="colorWhite"&amp;gt;#FFFFFF&amp;lt;/color&amp;gt;
    &amp;lt;color name="colorGray"&amp;gt;#E5E5E5&amp;lt;/color&amp;gt;
&amp;lt;/resources&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Desain Layout&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Buat beberapa layout berikut :&lt;br /&gt;
activity_main.xml
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:ignore="MergeRootFrame" /&amp;gt;
&lt;/pre&gt;
activity_detail.xml
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:ignore="MergeRootFrame" /&amp;gt;
&lt;/pre&gt;
toolbar.xml
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;android.support.v7.widget.Toolbar
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="?actionBarSize"
    android:background="?colorPrimary"
    app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" /&amp;gt;
&lt;/pre&gt;
fragment_main.xml
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"&amp;gt;

    &amp;lt;include layout="@layout/toolbar" /&amp;gt;

    &amp;lt;android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/refresh"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"&amp;gt;

        &amp;lt;android.support.v7.widget.RecyclerView
            android:id="@+id/rv_movies"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:padding="1dp"
            android:scrollbars="vertical"/&amp;gt;

    &amp;lt;/android.support.v4.widget.SwipeRefreshLayout&amp;gt;

&amp;lt;/LinearLayout&amp;gt;
&lt;/pre&gt;
fragment_detail.xml
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"&amp;gt;

    &amp;lt;include layout="@layout/toolbar" /&amp;gt;

    &amp;lt;ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"&amp;gt;

        &amp;lt;LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"&amp;gt;

            &amp;lt;LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:layout_margin="10dp"&amp;gt;

                &amp;lt;TextView
                    android:id="@+id/movie_title"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textAppearance="?android:attr/textAppearanceLarge"
                    android:text="@string/title"/&amp;gt;

            &amp;lt;/LinearLayout&amp;gt;

            &amp;lt;View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:layout_marginLeft="10dp"
                android:layout_marginRight="10dp"
                android:background="@color/colorPrimary"/&amp;gt;

            &amp;lt;LinearLayout
                android:orientation="horizontal"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="10dp"&amp;gt;

                &amp;lt;ImageView
                    android:id="@+id/img_poster"
                    android:layout_width="130dp"
                    android:layout_height="180dp"
                    android:scaleType="centerCrop"
                    tools:ignore="ContentDescription" /&amp;gt;

                &amp;lt;LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="vertical"
                    android:paddingRight="@dimen/activity_vertical_margin"
                    android:paddingLeft="@dimen/activity_vertical_margin"
                    android:paddingBottom="@dimen/activity_vertical_margin"&amp;gt;

                    &amp;lt;TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:textStyle="bold"
                        android:text="@string/release_date"/&amp;gt;

                    &amp;lt;TextView
                        android:id="@+id/movie_date"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"/&amp;gt;

                    &amp;lt;TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="5dp"
                        android:textStyle="bold"
                        android:text="@string/duration"/&amp;gt;

                    &amp;lt;TextView
                        android:id="@+id/movie_duration"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"/&amp;gt;

                    &amp;lt;TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="5dp"
                        android:textStyle="bold"
                        android:text="@string/genre"/&amp;gt;

                    &amp;lt;TextView
                        android:id="@+id/movie_genre"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"/&amp;gt;

                    &amp;lt;TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="5dp"
                        android:textStyle="bold"
                        android:text="@string/homepage"/&amp;gt;

                    &amp;lt;TextView
                        android:id="@+id/movie_homepage"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"/&amp;gt;

                &amp;lt;/LinearLayout&amp;gt;
            &amp;lt;/LinearLayout&amp;gt;

            &amp;lt;View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:layout_marginLeft="10dp"
                android:layout_marginRight="10dp"
                android:background="@color/colorPrimary"/&amp;gt;

            &amp;lt;LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:layout_margin="10dp"&amp;gt;

                &amp;lt;TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textStyle="bold"
                    android:text="@string/overview"/&amp;gt;

                &amp;lt;TextView
                    android:id="@+id/movie_overview"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"/&amp;gt;

            &amp;lt;/LinearLayout&amp;gt;

            &amp;lt;View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:layout_marginLeft="10dp"
                android:layout_marginRight="10dp"
                android:background="@color/colorPrimary"/&amp;gt;

            &amp;lt;LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:layout_margin="10dp"&amp;gt;

                &amp;lt;TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textStyle="bold"
                    android:text="@string/trailers"/&amp;gt;

                &amp;lt;ProgressBar
                    android:id="@+id/pg_trailers"
                    style="?android:attr/progressBarStyle"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_horizontal"
                    android:visibility="gone"/&amp;gt;

                &amp;lt;LinearLayout
                    android:id="@+id/view_trailers"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="vertical"/&amp;gt;

            &amp;lt;/LinearLayout&amp;gt;

            &amp;lt;View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:layout_marginLeft="10dp"
                android:layout_marginRight="10dp"
                android:background="@color/colorPrimary"/&amp;gt;

            &amp;lt;LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:layout_margin="10dp"&amp;gt;

                &amp;lt;TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textStyle="bold"
                    android:text="@string/reviews"/&amp;gt;

                &amp;lt;ProgressBar
                    android:id="@+id/pg_reviews"
                    style="?android:attr/progressBarStyle"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_horizontal"
                    android:visibility="gone"/&amp;gt;

                &amp;lt;LinearLayout
                    android:id="@+id/view_reviews"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="vertical"/&amp;gt;

            &amp;lt;/LinearLayout&amp;gt;

        &amp;lt;/LinearLayout&amp;gt;
    &amp;lt;/ScrollView&amp;gt;

&amp;lt;/LinearLayout&amp;gt;
&lt;/pre&gt;
list_item_movie.xml
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"&amp;gt;

    &amp;lt;ImageView
        android:id="@+id/img_thumb"
        android:layout_width="match_parent"
        android:layout_height="270dp"
        android:scaleType="centerCrop"
        tools:ignore="ContentDescription" /&amp;gt;

&amp;lt;/RelativeLayout&amp;gt;
&lt;/pre&gt;
list_item_review.xml
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"&amp;gt;

    &amp;lt;TextView
        android:id="@+id/reviewers"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="4dp"
        android:textStyle="bold"/&amp;gt;

    &amp;lt;TextView
        android:id="@+id/content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="4dp"/&amp;gt;

    &amp;lt;View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@color/colorGray"/&amp;gt;

&amp;lt;/LinearLayout&amp;gt;
&lt;/pre&gt;
list_item_trailer.xml
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"&amp;gt;

    &amp;lt;LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_margin="4dp"&amp;gt;

        &amp;lt;ImageView
            android:id="@+id/trailer_thumb"
            android:layout_width="80dp"
            android:layout_height="80dp"
            android:scaleType="centerCrop"
            tools:ignore="ContentDescription" /&amp;gt;

        &amp;lt;TextView
            android:id="@+id/trailer_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="4dp"
            android:layout_marginLeft="4dp"
            android:padding="4dp"/&amp;gt;

    &amp;lt;/LinearLayout&amp;gt;

    &amp;lt;View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@color/colorGray"/&amp;gt;

&amp;lt;/LinearLayout&amp;gt;
&lt;/pre&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Buat Kelas Java&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Selanjutnya adalah membuat kelas-kelas java. Kelas-kelas yang kita buat dibagi dibeberapa package berikut. 
&lt;br /&gt;
&lt;i&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/i&gt;
&lt;b&gt;- package model&amp;nbsp;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
BaseModel.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import com.google.gson.annotations.SerializedName;

import java.util.List;

/**
 * Created by Wim on 5/29/17.
 */

public class BaseModel&amp;lt;T&amp;gt; {

    @SerializedName("page")
    private int page;
    @SerializedName("results")
    private List&amp;lt;T&amp;gt; results;

    public BaseModel() {
    }

    public int getPage() {
        return page;
    }

    public void setPage(int page) {
        this.page = page;
    }

    public List&amp;lt;T&amp;gt; getResults() {
        return results;
    }

    public void setResults(List&amp;lt;T&amp;gt; results) {
        this.results = results;
    }

}
&lt;/pre&gt;
Genre.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import com.google.gson.annotations.SerializedName;

/**
 * Created by Wim on 6/2/17.
 */

public class Genre {

    @SerializedName("id")
    private int id;
    @SerializedName("name")
    private String name;

    public Genre() {
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

}
&lt;/pre&gt;
Movie.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import com.google.gson.annotations.SerializedName;

/**
 * Created by Wim on 5/29/17.
 */

public class Movie extends BaseModel&amp;lt;MovieData&amp;gt; {

    @SerializedName("total_results")
    private int totalResult;
    @SerializedName("total_pages")
    private int totalPages;

    public Movie() {
    }

    public int getTotalResult() {
        return totalResult;
    }

    public void setTotalResult(int totalResult) {
        this.totalResult = totalResult;
    }

    public int getTotalPages() {
        return totalPages;
    }

    public void setTotalPages(int totalPages) {
        this.totalPages = totalPages;
    }

}
&lt;/pre&gt;
MovieData.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import android.os.Parcel;
import android.os.Parcelable;

import com.google.gson.annotations.SerializedName;

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

/**
 * Created by Wim on 5/29/17.
 */

public class MovieData implements Parcelable {

    @SerializedName("id")
    private int id;
    @SerializedName("original_title")
    private String originalTitle;
    @SerializedName("original_language")
    private String originalLanguage;
    @SerializedName("title")
    private String title;
    @SerializedName("poster_path")
    private String posterPath;
    @SerializedName("adult")
    private boolean adult;
    @SerializedName("overview")
    private String overview;
    @SerializedName("release_date")
    private String releaseDate;
    @SerializedName("genre_ids")
    private List&amp;lt;Integer&amp;gt; genreIds;
    @SerializedName("backdrop_path")
    private String backdropPath;
    @SerializedName("popularity")
    private double popularity;
    @SerializedName("vote_count")
    private int voteCount;
    @SerializedName("video")
    private boolean video;
    @SerializedName("vote_average")
    private double voteAverage;

    public MovieData() {
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getOriginalTitle() {
        return originalTitle;
    }

    public void setOriginalTitle(String originalTitle) {
        this.originalTitle = originalTitle;
    }

    public String getOriginalLanguage() {
        return originalLanguage;
    }

    public void setOriginalLanguage(String originalLanguage) {
        this.originalLanguage = originalLanguage;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getPosterPath() {
        return posterPath;
    }

    public void setPosterPath(String posterPath) {
        this.posterPath = posterPath;
    }

    public boolean isAdult() {
        return adult;
    }

    public void setAdult(boolean adult) {
        this.adult = adult;
    }

    public String getOverview() {
        return overview;
    }

    public void setOverview(String overview) {
        this.overview = overview;
    }

    public String getReleaseDate() {
        return releaseDate;
    }

    public void setReleaseDate(String releaseDate) {
        this.releaseDate = releaseDate;
    }

    public List&amp;lt;Integer&amp;gt; getGenreIds() {
        return genreIds;
    }

    public void setGenreIds(List&amp;lt;Integer&amp;gt; genreIds) {
        this.genreIds = genreIds;
    }

    public String getBackdropPath() {
        return backdropPath;
    }

    public void setBackdropPath(String backdropPath) {
        this.backdropPath = backdropPath;
    }

    public double getPopularity() {
        return popularity;
    }

    public void setPopularity(double popularity) {
        this.popularity = popularity;
    }

    public int getVoteCount() {
        return voteCount;
    }

    public void setVoteCount(int voteCount) {
        this.voteCount = voteCount;
    }

    public boolean isVideo() {
        return video;
    }

    public void setVideo(boolean video) {
        this.video = video;
    }

    public double getVoteAverage() {
        return voteAverage;
    }

    public void setVoteAverage(double voteAverage) {
        this.voteAverage = voteAverage;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(this.id);
        dest.writeString(this.originalTitle);
        dest.writeString(this.originalLanguage);
        dest.writeString(this.title);
        dest.writeString(this.posterPath);
        dest.writeByte(this.adult ? (byte) 1 : (byte) 0);
        dest.writeString(this.overview);
        dest.writeString(this.releaseDate);
        dest.writeList(this.genreIds);
        dest.writeString(this.backdropPath);
        dest.writeDouble(this.popularity);
        dest.writeInt(this.voteCount);
        dest.writeByte(this.video ? (byte) 1 : (byte) 0);
        dest.writeDouble(this.voteAverage);
    }

    protected MovieData(Parcel in) {
        this.id = in.readInt();
        this.originalTitle = in.readString();
        this.originalLanguage = in.readString();
        this.title = in.readString();
        this.posterPath = in.readString();
        this.adult = in.readByte() != 0;
        this.overview = in.readString();
        this.releaseDate = in.readString();
        this.genreIds = new ArrayList&amp;lt;Integer&amp;gt;();
        in.readList(this.genreIds, Integer.class.getClassLoader());
        this.backdropPath = in.readString();
        this.popularity = in.readDouble();
        this.voteCount = in.readInt();
        this.video = in.readByte() != 0;
        this.voteAverage = in.readDouble();
    }

    public static final Parcelable.Creator&amp;lt;MovieData&amp;gt; CREATOR = new Parcelable.Creator&amp;lt;MovieData&amp;gt;() {
        @Override
        public MovieData createFromParcel(Parcel source) {
            return new MovieData(source);
        }

        @Override
        public MovieData[] newArray(int size) {
            return new MovieData[size];
        }
    };

}
&lt;/pre&gt;
MovieDetail.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import com.google.gson.annotations.SerializedName;

import java.util.List;

/**
 * Created by Wim on 6/2/17.
 */

public class MovieDetail {

    @SerializedName("id")
    private int id;
    @SerializedName("original_language")
    private String originalLanguage;
    @SerializedName("original_title")
    private String originalTitle;
    @SerializedName("overview")
    private String overview;
    @SerializedName("poster_path")
    private String posterPath;
    @SerializedName("release_date")
    private String releaseDate;
    @SerializedName("runtime")
    private int runtime;
    @SerializedName("vote_average")
    private double voteAverage;
    @SerializedName("homepage")
    private String homepage;
    @SerializedName("genres")
    private List&amp;lt;Genre&amp;gt; genres;

    public MovieDetail() {
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getOriginalLanguage() {
        return originalLanguage;
    }

    public void setOriginalLanguage(String originalLanguage) {
        this.originalLanguage = originalLanguage;
    }

    public String getOriginalTitle() {
        return originalTitle;
    }

    public void setOriginalTitle(String originalTitle) {
        this.originalTitle = originalTitle;
    }

    public String getOverview() {
        return overview;
    }

    public void setOverview(String overview) {
        this.overview = overview;
    }

    public String getPosterPath() {
        return posterPath;
    }

    public void setPosterPath(String posterPath) {
        this.posterPath = posterPath;
    }

    public String getReleaseDate() {
        return releaseDate;
    }

    public void setReleaseDate(String releaseDate) {
        this.releaseDate = releaseDate;
    }

    public int getRuntime() {
        return runtime;
    }

    public void setRuntime(int runtime) {
        this.runtime = runtime;
    }

    public double getVoteAverage() {
        return voteAverage;
    }

    public void setVoteAverage(double voteAverage) {
        this.voteAverage = voteAverage;
    }

    public String getHomepage() {
        return homepage;
    }

    public void setHomepage(String homepage) {
        this.homepage = homepage;
    }

    public List&amp;lt;Genre&amp;gt; getGenres() {
        return genres;
    }

    public void setGenres(List&amp;lt;Genre&amp;gt; genres) {
        this.genres = genres;
    }
}
&lt;/pre&gt;
Review.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import com.google.gson.annotations.SerializedName;

/**
 * Created by Wim on 5/29/17.
 */

public class Review extends BaseModel&amp;lt;ReviewData&amp;gt; {

    @SerializedName("id")
    private int id;
    @SerializedName("total_pages")
    private int totalPages;
    @SerializedName("total_results")
    private int totalResults;

    public Review() {
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getTotalPages() {
        return totalPages;
    }

    public void setTotalPages(int totalPages) {
        this.totalPages = totalPages;
    }

    public int getTotalResults() {
        return totalResults;
    }

    public void setTotalResults(int totalResults) {
        this.totalResults = totalResults;
    }
}
&lt;/pre&gt;
ReviewData.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;/**
 * Created by Wim on 5/29/17.
 */

public class ReviewData {

    private String id;
    private String author;
    private String content;
    private String url;

    public ReviewData() {
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

}
&lt;/pre&gt;
Trailer.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import com.google.gson.annotations.SerializedName;

/**
 * Created by Wim on 5/29/17.
 */

public class Trailer extends BaseModel&amp;lt;TrailerData&amp;gt; {

    @SerializedName("id")
    private int id;

    public Trailer() {
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

}
&lt;/pre&gt;
TrailerData.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import com.google.gson.annotations.SerializedName;

/**
 * Created by Wim on 5/29/17.
 */

public class TrailerData {

    @SerializedName("id")
    private String id;
    @SerializedName("key")
    private String key;
    @SerializedName("name")
    private String name;
    @SerializedName("site")
    private String site;
    @SerializedName("size")
    private int size;
    @SerializedName("type")
    private String type;

    public TrailerData() {
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public String getName() {
        return name;
    }

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

    public String getSite() {
        return site;
    }

    public void setSite(String site) {
        this.site = site;
    }

    public int getSize() {
        return size;
    }

    public void setSize(int size) {
        this.size = size;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

}
&lt;/pre&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;b&gt;- package network&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Constant.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import id.co.blogspot.wimsonevel.android_moviedb.BuildConfig;

/**
 * Created by Wim on 5/29/17.
 */

public class Constant {

    public static final String BASE_URL = BuildConfig.BASE_URL;
    public static final String IMG_URL = BuildConfig.IMG_URL;
    public static final String API_KEY = BuildConfig.MOVIE_API_KEY;
    public static final String VERSION = "/3";
    public static final String MOVIE = "/movie";
    public static final String VIDEOS = "videos";
    public static final String REVIEWS = "reviews";
    public static final String LANG_EN = "en-US";

    public static final String MOVIE_PATH = VERSION + MOVIE;

}
&lt;/pre&gt;
ApiInterface.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import id.co.blogspot.wimsonevel.android_moviedb.model.Movie;
import id.co.blogspot.wimsonevel.android_moviedb.model.MovieDetail;
import id.co.blogspot.wimsonevel.android_moviedb.model.Review;
import id.co.blogspot.wimsonevel.android_moviedb.model.Trailer;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Path;
import retrofit2.http.Query;

/**
 * Created by Wim on 6/2/17.
 */

public interface ApiInterface {

    @GET(Constant.MOVIE_PATH + "/popular")
    Call&amp;lt;Movie&amp;gt; popularMovies(
            @Query("page") int page);

    @GET(Constant.MOVIE_PATH + "/{movie_id}")
    Call&amp;lt;MovieDetail&amp;gt; movieDetail(
            @Path("movie_id") int movieId);

    @GET(Constant.MOVIE_PATH + "/{movie_id}/" + Constant.VIDEOS)
    Call&amp;lt;Trailer&amp;gt; trailers(
            @Path("movie_id") int movieId);

    @GET(Constant.MOVIE_PATH + "/{movie_id}/" + Constant.REVIEWS)
    Call&amp;lt;Review&amp;gt; reviews(
            @Path("movie_id") int movieId);

}
&lt;/pre&gt;
ApiService.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import java.io.IOException;
import java.util.concurrent.TimeUnit;

import id.co.blogspot.wimsonevel.android_moviedb.BuildConfig;
import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Callback;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * Created by Wim on 6/2/17.
 */

public class ApiService {

    private ApiInterface apiInterface;

    public ApiService(){
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(Constant.BASE_URL)
                .client(builder())
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        apiInterface = retrofit.create(ApiInterface.class);
    }

    private OkHttpClient builder() {
        OkHttpClient.Builder okHttpClient = new OkHttpClient().newBuilder();
        okHttpClient.connectTimeout(20, TimeUnit.SECONDS);
        okHttpClient.writeTimeout(20, TimeUnit.SECONDS);
        okHttpClient.readTimeout(90, TimeUnit.SECONDS);

        if (BuildConfig.DEBUG) {
            okHttpClient.addInterceptor(interceptor());
        }

        okHttpClient.addInterceptor(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                HttpUrl url = request.url()
                        .newBuilder()
                        .addQueryParameter("api_key", Constant.API_KEY)
                        .addQueryParameter("language", Constant.LANG_EN)
                        .build();

                request = request.newBuilder().url(url).build();
                return chain.proceed(request);
            }
        });

        return okHttpClient.build();
    }
    private static HttpLoggingInterceptor interceptor() {
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

        return interceptor;
    }

    public void getPopularMovies(int page, Callback callback) {
        apiInterface.popularMovies(page).enqueue(callback);
    }

    public void getMovieDetail(int movieId, Callback callback) {
        apiInterface.movieDetail(movieId).enqueue(callback);
    }

    public void getTrailers(int movieId, Callback callback) {
        apiInterface.trailers(movieId).enqueue(callback);
    }

    public void getReviews(int movieId, Callback callback) {
        apiInterface.reviews(movieId).enqueue(callback);
    }
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;- package util&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
ConnectionUtil.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;

/**
 * Created by Wim on 5/29/17.
 */

public class ConnectionUtil {

    public static boolean isConnected(Context context) {
        ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();

        return activeNetwork != null &amp;amp;&amp;amp; activeNetwork.isConnectedOrConnecting();
    }

}

&lt;/pre&gt;
EndlessRecyclerOnScrollListener.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;

/**
 * Created by Wim on 5/29/17.
 */

public abstract class EndlessRecyclerOnScrollListener extends RecyclerView.OnScrollListener {

    private int previousTotal = 0;
    private boolean loading = true;
    private int visibleThreshold = 1;
    int firstVisibleItem, visibleItemCount, totalItemCount;

    private int offset = 0;
    private int limit = 0;

    private RecyclerView.LayoutManager mLayoutManager;
    private boolean isUseLinearLayoutManager = false;

    public EndlessRecyclerOnScrollListener(LinearLayoutManager linearLayoutManager, int offset, int limit) {
        this.mLayoutManager = linearLayoutManager;
        isUseLinearLayoutManager = true;
        this.offset = offset;
    }

    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);

        if (isUseLinearLayoutManager &amp;amp;&amp;amp; mLayoutManager instanceof LinearLayoutManager) {
            firstVisibleItem = ((LinearLayoutManager) mLayoutManager).findFirstVisibleItemPosition();
        }

        visibleItemCount = mLayoutManager.getChildCount();
        totalItemCount = mLayoutManager.getItemCount();

        if (loading) {
            if (totalItemCount &amp;gt; previousTotal) {
                loading = false;
                previousTotal = totalItemCount;
            }
        }
        if (!loading &amp;amp;&amp;amp; (totalItemCount - visibleItemCount)
                &amp;lt;= (firstVisibleItem + visibleThreshold)
                &amp;amp;&amp;amp; totalItemCount &amp;gt;= limit) {
            // End has been reached

            // Do something
            offset++;
            onLoadMore(offset);

            loading = true;
        }
    }

    public abstract void onLoadMore(int offset);
}
&lt;/pre&gt;
GridMarginDecoration.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import android.content.Context;
import android.graphics.Rect;
import android.support.v7.widget.RecyclerView;
import android.view.View;

/**
 * Created by Wim on 5/29/17.
 */

public class GridMarginDecoration extends RecyclerView.ItemDecoration {

    private int left;
    private int right;
    private int top;
    private int bottom;

    public GridMarginDecoration(Context context, int left, int right, int top, int bottom) {
        this.left = left;
        this.right = right;
        this.top = top;
        this.bottom = bottom;
    }

    @Override
    public void getItemOffsets(
            Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        outRect.set(left, top, right, bottom);
    }

}

&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;- package adapter&amp;nbsp;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
MovieListAdapter.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

import com.squareup.picasso.Picasso;

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

import id.co.blogspot.wimsonevel.android_moviedb.R;
import id.co.blogspot.wimsonevel.android_moviedb.model.MovieData;
import id.co.blogspot.wimsonevel.android_moviedb.network.Constant;

/**
 * Created by Wim on 5/29/17.
 */

public class MovieListAdapter extends RecyclerView.Adapter&amp;lt;MovieListAdapter.MovieViewHolder&amp;gt; {

    private List&amp;lt;MovieData&amp;gt; movieDatas;
    private Context context;

    private OnMovieItemSelectedListener onMovieItemSelectedListener;

    public MovieListAdapter(Context context) {
        this.context = context;
        movieDatas = new ArrayList&amp;lt;&amp;gt;();
    }

    private void add(MovieData item) {
        movieDatas.add(item);
        notifyItemInserted(movieDatas.size() - 1);
    }

    public void addAll(List&amp;lt;MovieData&amp;gt; movieDatas) {
        for (MovieData movieData : movieDatas) {
            add(movieData);
        }
    }

    public void remove(MovieData item) {
        int position = movieDatas.indexOf(item);
        if (position &amp;gt; -1) {
            movieDatas.remove(position);
            notifyItemRemoved(position);
        }
    }

    public void clear() {
        while (getItemCount() &amp;gt; 0) {
            remove(getItem(0));
        }
    }

    public MovieData getItem(int position) {
        return movieDatas.get(position);
    }

    @Override
    public MovieViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_movie, parent, false);
        final MovieViewHolder movieViewHolder = new MovieViewHolder(view);
        movieViewHolder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int adapterPos = movieViewHolder.getAdapterPosition();
                if (adapterPos != RecyclerView.NO_POSITION) {
                    if (onMovieItemSelectedListener != null) {
                        onMovieItemSelectedListener.onItemClick(movieViewHolder.itemView, adapterPos);
                    }
                }
            }
        });

        return movieViewHolder;
    }

    @Override
    public void onBindViewHolder(MovieViewHolder holder, int position) {
        final MovieData movieData = movieDatas.get(position);
        holder.bind(movieData);
    }

    @Override
    public int getItemCount() {
        return movieDatas.size();
    }

    public void setOnMovieItemSelectedListener(OnMovieItemSelectedListener onMovieItemSelectedListener) {
        this.onMovieItemSelectedListener = onMovieItemSelectedListener;
    }

    public class MovieViewHolder extends RecyclerView.ViewHolder {
        ImageView img;

        public MovieViewHolder(View itemView) {
            super(itemView);

            img = (ImageView) itemView.findViewById(R.id.img_thumb);
        }

        public void bind(MovieData movieData) {
            Picasso.with(context)
                    .load(Constant.IMG_URL + movieData.getPosterPath())
                    .into(img);
        }
    }

    public interface OnMovieItemSelectedListener {
        void onItemClick(View v, int position);
    }

}
&lt;/pre&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;b&gt;- package fragment&amp;nbsp;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
MainFragment.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import java.net.SocketTimeoutException;

import id.co.blogspot.wimsonevel.android_moviedb.DetailActivity;
import id.co.blogspot.wimsonevel.android_moviedb.R;
import id.co.blogspot.wimsonevel.android_moviedb.adapter.MovieListAdapter;
import id.co.blogspot.wimsonevel.android_moviedb.model.Movie;
import id.co.blogspot.wimsonevel.android_moviedb.network.ApiService;
import id.co.blogspot.wimsonevel.android_moviedb.util.EndlessRecyclerOnScrollListener;
import id.co.blogspot.wimsonevel.android_moviedb.util.GridMarginDecoration;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

/**
 * Created by Wim on 5/29/17.
 */

public class MainFragment extends Fragment implements MovieListAdapter.OnMovieItemSelectedListener {

    private Toolbar toolbar;
    private RecyclerView rvMovies;
    private GridLayoutManager gridLayoutManager;
    private MovieListAdapter movieListAdapter;
    private SwipeRefreshLayout refreshLayout;

    private ActionBar actionBar;
    private int page = 1;
    private int limit = 20;

    private EndlessRecyclerOnScrollListener endlessRecyclerOnScrollListener;

    private ApiService apiService;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_main, container, false);

        toolbar = (Toolbar) view.findViewById(R.id.toolbar);
        refreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.refresh);
        rvMovies = (RecyclerView) view.findViewById(R.id.rv_movies);

        return view;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        if(savedInstanceState == null) {
            ((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);

            actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
            if (actionBar != null) {
                actionBar.setTitle(R.string.app_name);
                actionBar.setSubtitle(R.string.most_popular);
            }

            movieListAdapter = new MovieListAdapter(getContext());
            movieListAdapter.setOnMovieItemSelectedListener(this);

            gridLayoutManager = new GridLayoutManager(getContext(), 2);
            rvMovies.setLayoutManager(gridLayoutManager);

            rvMovies.addItemDecoration(new GridMarginDecoration(getContext(), 1, 1, 1, 1));
            rvMovies.setHasFixedSize(true);
            rvMovies.setAdapter(movieListAdapter);

            addScroll();

            refreshLayout.setColorSchemeResources(R.color.colorPrimary);
            refreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
                @Override
                public void onRefresh() {
                    refreshData();
                }
            });

            loadData();
        }
    }

    private void addScroll() {
        endlessRecyclerOnScrollListener = new EndlessRecyclerOnScrollListener(gridLayoutManager, page, limit) {
            @Override
            public void onLoadMore(int next) {
                page = next;
                loadData();
            }
        };

        rvMovies.addOnScrollListener(endlessRecyclerOnScrollListener);
    }

    private void removeScroll() {
        rvMovies.removeOnScrollListener(endlessRecyclerOnScrollListener);
    }

    private void loadData(){
        if (refreshLayout != null) {
            refreshLayout.post(new Runnable() {
                @Override
                public void run() {
                    refreshLayout.setRefreshing(true);
                }
            });
        }

        apiService = new ApiService();
        apiService.getPopularMovies(page, new Callback() {
            @Override
            public void onResponse(Call call, Response response) {
                Movie movie = (Movie) response.body();

                if(movie != null) {
                    if(movieListAdapter != null) {
                        movieListAdapter.addAll(movie.getResults());
                    }
                }else{
                    Toast.makeText(getContext(), "No Data!", Toast.LENGTH_LONG).show();
                }

                if (refreshLayout != null)
                    refreshLayout.setRefreshing(false);
            }

            @Override
            public void onFailure(Call call, Throwable t) {
                if(t instanceof SocketTimeoutException) {
                    Toast.makeText(getContext(), "Request Timeout. Please try again!", Toast.LENGTH_LONG).show();
                }else{
                    Toast.makeText(getContext(), "Connection Error!", Toast.LENGTH_LONG).show();
                }

                if (refreshLayout != null)
                    refreshLayout.setRefreshing(false);
            }
        });
    }

    private void refreshData() {
        if(movieListAdapter != null) {
            movieListAdapter.clear();
        }
        page = 1;

        limit = 20;

        removeScroll();
        addScroll();

        loadData();
    }

    @Override
    public void onItemClick(View v, int position) {
        DetailActivity.start(getContext(), movieListAdapter.getItem(position));
    }

}
&lt;/pre&gt;
DetailFragment.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.squareup.picasso.Picasso;

import java.net.SocketTimeoutException;
import java.util.List;

import id.co.blogspot.wimsonevel.android_moviedb.R;
import id.co.blogspot.wimsonevel.android_moviedb.model.Genre;
import id.co.blogspot.wimsonevel.android_moviedb.model.MovieData;
import id.co.blogspot.wimsonevel.android_moviedb.model.MovieDetail;
import id.co.blogspot.wimsonevel.android_moviedb.model.Review;
import id.co.blogspot.wimsonevel.android_moviedb.model.ReviewData;
import id.co.blogspot.wimsonevel.android_moviedb.model.Trailer;
import id.co.blogspot.wimsonevel.android_moviedb.model.TrailerData;
import id.co.blogspot.wimsonevel.android_moviedb.network.ApiService;
import id.co.blogspot.wimsonevel.android_moviedb.network.Constant;
import id.co.blogspot.wimsonevel.android_moviedb.util.ConnectionUtil;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

/**
 * Created by Wim on 5/29/17.
 */

public class DetailFragment extends Fragment {

    private Toolbar toolbar;
    private ImageView imgPoster;
    private TextView tvMovieTitle;
    private TextView tvMovieDate;
    private TextView tvMovieDuration;
    private TextView tvMovieGenre;
    private TextView tvMovieHomepage;
    private TextView tvMovieOverview;
    private LinearLayout viewTrailers;
    private LinearLayout viewReviews;

    private ProgressBar pgTrailers;
    private ProgressBar pgReviews;

    private MovieData movieData;

    private ApiService apiService;

    public static DetailFragment newInstance(MovieData movieData) {
        Bundle bundle = new Bundle();
        bundle.putParcelable(DetailFragment.class.getSimpleName(), movieData);
        DetailFragment detailFragment = new DetailFragment();
        detailFragment.setArguments(bundle);
        return detailFragment;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_detail, container, false);

        toolbar = (Toolbar) view.findViewById(R.id.toolbar);
        imgPoster = (ImageView) view.findViewById(R.id.img_poster);
        tvMovieTitle = (TextView) view.findViewById(R.id.movie_title);
        tvMovieDate = (TextView) view.findViewById(R.id.movie_date);
        tvMovieDuration = (TextView) view.findViewById(R.id.movie_duration);
        tvMovieGenre = (TextView) view.findViewById(R.id.movie_genre);
        tvMovieHomepage = (TextView) view.findViewById(R.id.movie_homepage);
        tvMovieOverview = (TextView) view.findViewById(R.id.movie_overview);
        viewTrailers = (LinearLayout) view.findViewById(R.id.view_trailers);
        viewReviews = (LinearLayout) view.findViewById(R.id.view_reviews);

        pgTrailers = (ProgressBar) view.findViewById(R.id.pg_trailers);
        pgReviews = (ProgressBar) view.findViewById(R.id.pg_reviews);

        return view;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        ((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);

        ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
        if (actionBar != null) {
            actionBar.setDisplayHomeAsUpEnabled(true);
            actionBar.setTitle(R.string.app_name);
            actionBar.setSubtitle(R.string.movie_detail);
        }

        movieData = getArguments().getParcelable(DetailFragment.class.getSimpleName());

        apiService = new ApiService();

        if(ConnectionUtil.isConnected(getContext())) {
            if(movieData != null) {
                loadMovieDetail(movieData.getId());
                loadTrailer(movieData.getId());
                loadReviews(movieData.getId());
            }
        }else{
            Toast.makeText(getContext(), "No Internet Connection", Toast.LENGTH_LONG).show();
        }
    }

    private void loadMovieDetail(int id) {
        apiService.getMovieDetail(id, new Callback() {
            @Override
            public void onResponse(Call call, Response response) {
                MovieDetail movieDetail = (MovieDetail) response.body();

                if(movieDetail != null) {
                    Picasso.with(getContext())
                            .load(Constant.IMG_URL + movieDetail.getPosterPath())
                            .into(imgPoster);

                    tvMovieTitle.setText(movieDetail.getOriginalTitle());
                    tvMovieDate.setText(movieDetail.getReleaseDate());
                    tvMovieDuration.setText(movieDetail.getRuntime() + " Minutes");

                    for (int i = 0; i &amp;lt; movieDetail.getGenres().size(); i++) {
                        Genre genre = movieDetail.getGenres().get(i);

                        if(i &amp;lt; movieDetail.getGenres().size() - 1) {
                            tvMovieGenre.append(genre.getName() + ",");
                        }else{
                            tvMovieGenre.append(genre.getName());
                        }
                    }

                    tvMovieHomepage.setText(movieDetail.getHomepage());
                    tvMovieOverview.setText(movieDetail.getOverview());
                }else{
                    Toast.makeText(getContext(), "No Data!", Toast.LENGTH_LONG).show();
                }
            }

            @Override
            public void onFailure(Call call, Throwable t) {
                if(t instanceof SocketTimeoutException) {
                    Toast.makeText(getContext(), "Request Timeout. Please try again!", Toast.LENGTH_LONG).show();
                }else{
                    Toast.makeText(getContext(), "Connection Error!", Toast.LENGTH_LONG).show();
                }

            }
        });
    }

    private void loadTrailer(int id) {
        pgTrailers.setVisibility(View.VISIBLE);

        apiService.getTrailers(id, new Callback() {
            @Override
            public void onResponse(Call call, Response response) {
                Trailer trailer = (Trailer) response.body();

                if(trailer != null) {
                    showTrailers(trailer.getResults());
                }else{
                    Toast.makeText(getContext(), "No Data!", Toast.LENGTH_LONG).show();
                }

                pgTrailers.setVisibility(View.GONE);
            }

            @Override
            public void onFailure(Call call, Throwable t) {
                if(t instanceof SocketTimeoutException) {
                    Toast.makeText(getContext(), "Request Timeout. Please try again!", Toast.LENGTH_LONG).show();
                }else{
                    Toast.makeText(getContext(), "Connection Error!", Toast.LENGTH_LONG).show();
                }

                pgTrailers.setVisibility(View.GONE);
            }
        });
    }

    private void loadReviews(int id) {
        pgReviews.setVisibility(View.VISIBLE);

        apiService.getReviews(id, new Callback() {
            @Override
            public void onResponse(Call call, Response response) {
                Review review = (Review) response.body();

                if(review != null) {
                    showReviews(review.getResults());
                }else{
                    Toast.makeText(getContext(), "No Data!", Toast.LENGTH_LONG).show();
                }

                pgReviews.setVisibility(View.GONE);
            }

            @Override
            public void onFailure(Call call, Throwable t) {
                if(t instanceof SocketTimeoutException) {
                    Toast.makeText(getContext(), "Request Timeout. Please try again!", Toast.LENGTH_LONG).show();
                }else{
                    Toast.makeText(getContext(), "Connection Error!", Toast.LENGTH_LONG).show();
                }

                pgReviews.setVisibility(View.GONE);
            }
        });
    }

    private void showTrailers(List&amp;lt;TrailerData&amp;gt; trailerDatas) {
        viewTrailers.removeAllViews();

        for (int i = 0; i &amp;lt; trailerDatas.size(); i++) {

            final TrailerData trailerData = trailerDatas.get(i);
            View view = LayoutInflater.from(getContext()).inflate(R.layout.list_item_trailer, viewTrailers, false);

            ImageView trailerThumb = (ImageView) view.findViewById(R.id.trailer_thumb);
            TextView trailerName = (TextView) view.findViewById(R.id.trailer_name);

            if(trailerData.getSite().equalsIgnoreCase("youtube")) {
                Picasso.with(getContext())
                        .load("http://img.youtube.com/vi/" + trailerData.getKey() + "/default.jpg")
                        .into(trailerThumb);
            }

            view.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    watchYoutubeVideo(trailerData.getKey());
                }
            });


            trailerName.setText(trailerData.getName());
            viewTrailers.addView(view);
        }
    }

    public void watchYoutubeVideo(String id){
        Intent appIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("vnd.youtube:" + id));
        Intent webIntent = new Intent(Intent.ACTION_VIEW,
                Uri.parse("http://www.youtube.com/watch?v=" + id));
        try {
            startActivity(appIntent);
        } catch (ActivityNotFoundException ex) {
            startActivity(webIntent);
        }
    }

    private void showReviews(List&amp;lt;ReviewData&amp;gt; reviewDatas) {
        viewReviews.removeAllViews();

        for (int i = 0; i &amp;lt; reviewDatas.size(); i++) {

            ReviewData reviewData = reviewDatas.get(i);
            View view = LayoutInflater.from(getContext()).inflate(R.layout.list_item_review, viewReviews, false);

            TextView reviewers = (TextView) view.findViewById(R.id.reviewers);
            TextView content = (TextView) view.findViewById(R.id.content);

            reviewers.setText(reviewData.getAuthor());
            content.setText(reviewData.getContent().length() &amp;gt; 100 ?
                    reviewData.getContent().substring(0, 100) + "..." : reviewData.getContent());

            viewReviews.addView(view);
        }
    }

}
&lt;/pre&gt;
&lt;br /&gt;
Langkah selanjutnya adalah buat activity berikut :&lt;br /&gt;
&lt;br /&gt;
MainActivity.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import id.co.blogspot.wimsonevel.android_moviedb.fragment.MainFragment;

public class MainActivity extends AppCompatActivity {

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

        if(savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.container, new MainFragment())
                    .commit();
        }
    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();
    }

}
&lt;/pre&gt;
DetailActivity.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;

import id.co.blogspot.wimsonevel.android_moviedb.fragment.DetailFragment;
import id.co.blogspot.wimsonevel.android_moviedb.model.MovieData;

/**
 * Created by Wim on 5/29/17.
 */

public class DetailActivity extends AppCompatActivity {

    public static void start(Context context, MovieData movieData) {
        Intent intent = new Intent(context, DetailActivity.class);
        intent.putExtra(DetailActivity.class.getSimpleName(), movieData);
        context.startActivity(intent);
    }

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

        MovieData movieData = getIntent().getParcelableExtra(DetailActivity.class.getSimpleName());

        if(savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.container, DetailFragment.newInstance(movieData))
                    .commit();
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if(id == android.R.id.home) {
            onBackPressed();
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

}
&lt;/pre&gt;
Terakhir, tambahkan permission di AndroidManifest.xml
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="id.co.blogspot.wimsonevel.android_moviedb"&amp;gt;

    &amp;lt;uses-permission android:name="android.permission.INTERNET" /&amp;gt;
    &amp;lt;uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/&amp;gt;

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

                &amp;lt;category android:name="android.intent.category.LAUNCHER" /&amp;gt;
            &amp;lt;/intent-filter&amp;gt;
        &amp;lt;/activity&amp;gt;

        &amp;lt;activity
            android:name=".DetailActivity"
            android:launchMode="singleTask"
            android:screenOrientation="portrait"
            android:windowSoftInputMode="stateHidden"/&amp;gt;

    &amp;lt;/application&amp;gt;

&amp;lt;/manifest&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
Build dan jalankan maka tampilan aplikasinya seperti ini :&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmW3RhFDPxf26OqB7XMzlshRueFcl-Q7NMVL90YZaTs6BFWQ7KEuiMRenZxDOFRdDHEvZ3vgriQ9AcKy1MDgQ3pNQDqAvqbO7CVhfRD_C46hIDvviMH8nWYM-3fay-XOFnaJtoJ7NsKXw/s1600/Screenshot_1499074164.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="1600" data-original-width="900" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmW3RhFDPxf26OqB7XMzlshRueFcl-Q7NMVL90YZaTs6BFWQ7KEuiMRenZxDOFRdDHEvZ3vgriQ9AcKy1MDgQ3pNQDqAvqbO7CVhfRD_C46hIDvviMH8nWYM-3fay-XOFnaJtoJ7NsKXw/s400/Screenshot_1499074164.png" width="225" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg049Ia9DQrIrAEucWZ97kncAwrbKQyjxv-9j1paJRrWTbsIUnGIj7T7DEAlmZBNmCbpxQnUm36NIEoYRScaBhvpn-C9lWk7iCCrMCx3QAl4Fwbt2XEqKVdxh3IDWBhd5Y0f1orSKe6w3o/s1600/Screenshot_1499074173.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="1600" data-original-width="900" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg049Ia9DQrIrAEucWZ97kncAwrbKQyjxv-9j1paJRrWTbsIUnGIj7T7DEAlmZBNmCbpxQnUm36NIEoYRScaBhvpn-C9lWk7iCCrMCx3QAl4Fwbt2XEqKVdxh3IDWBhd5Y0f1orSKe6w3o/s400/Screenshot_1499074173.png" width="225" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Selesai akhirnyaaaa...&lt;br /&gt;
&lt;br /&gt;
Project Lengkap dapat di download di&amp;nbsp;&lt;a href="https://github.com/wimsonevel/Android-MovieDB"&gt;https://github.com/wimsonevel/Android-MovieDB&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Sekian dari saya kali ini semoga bermanfaat :)</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_yloCLtdnGMuezr83jzkkgbKnQDr5s9qc-sMfDCy9pd07J9EyySY-Hk1uqwVfDCBNZoBXJTia2hG7jv2a_IoEsbev194dzwNOhSodlcC94CaYdAzvjG9Znxl5Fp05Yju2t68g9sr14iQ/s72-c/android_retrofit.png" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">11</thr:total></item><item><title>(Tutorial Android) MVP Architecture on Android</title><link>http://wimsonevel.blogspot.com/2017/05/tutorial-android-mvp-architecture-on.html</link><category>Android</category><author>noreply@blogger.com (Wim Sonevel)</author><pubDate>Sat, 6 May 2017 23:05:00 +0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-6966757688576433754.post-3224713962722144175</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLgm_7x0NCYKPtiJjRfDuwY1lfCBfoNvfEGWb4sy4LrpJaXwwAE21R_ABmnLeei4W4OJploLHR74o5zvMbE4xMgIwGzHpHCnuRkOfvbvgyNhwp2pZNjkj34b0RlaIubk5d7GALSXKhcok/s1600/android+mvp.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="800" data-original-width="1280" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLgm_7x0NCYKPtiJjRfDuwY1lfCBfoNvfEGWb4sy4LrpJaXwwAE21R_ABmnLeei4W4OJploLHR74o5zvMbE4xMgIwGzHpHCnuRkOfvbvgyNhwp2pZNjkj34b0RlaIubk5d7GALSXKhcok/s640/android+mvp.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;b&gt;MVP&lt;/b&gt; merupakan singkatan dari &lt;b&gt;Model-View-Presenter&lt;/b&gt;. &lt;b&gt;MVP&lt;/b&gt; adalah arsitektur atau design pattern yang memisahkan antara proses bisnis dan logic di luar dari Activity dan Fragment serta membuatnya menjadi lifecycle tersendiri. Dengan menggunakan arsitektur &lt;b&gt;MVP&lt;/b&gt; dapat membuat pengembangan aplikasi Android yang kompleks jadi lebih mudah dan simpel, jumlah kode program menjadi lebih sedikit serta mudah di maintenance.&lt;br /&gt;
&lt;br /&gt;
Berikut penjelasan dari masing-masing layer di &lt;b&gt;MVP&lt;/b&gt;  :&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;View&lt;/b&gt; : Layer ini merupakan layer untuk menampilkan data dan interaksi ke user. View biasanya ditempatkan di Activity, Fragment atau Dialog di Android.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Model&lt;/b&gt; : Layer ini merupakan layer untuk mengakses data dari local maupun remote server.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Presenter&lt;/b&gt; : Layer ini merupakan layer yang menjembatani antara &lt;b&gt;Model&lt;/b&gt; dan &lt;b&gt;View&lt;/b&gt;. &lt;b&gt;Presenter&lt;/b&gt; juga dapat berjalan di background task. &lt;br /&gt;
&lt;br /&gt;
&lt;div style="line-height: 100%; margin-bottom: 0in;"&gt;
Pada kesempatan kali
ini, kita akan coba membuat sebuah aplikasi dengan arsitektur &lt;b&gt;MVP&lt;/b&gt;.&lt;/div&gt;
&lt;style type="text/css"&gt;
  @page { margin: 0.79in }
  p { margin-bottom: 0.1in; line-height: 120% }
 &lt;/style&gt;



&lt;br /&gt;
&lt;div style="line-height: 100%; margin-bottom: 0in;"&gt;
Buat project baru
kemudian buat sistem package seperti berikut :&lt;/div&gt;
&lt;div style="line-height: 100%; margin-bottom: 0in;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="line-height: 100%; margin-bottom: 0in;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipSic4ATQbM3XDxpkY9KtnXj7jCf7lE4BS6tiXkkEF4t0y3DUuiB57Z5AMcjCGrEtmuXNjQA1WLviDdMQKICuL7Y3MA_oDQinY7Ezj9FPVzpcutS1DNcsm6aTS25OoU7XCETCY6s4ZUjQ/s1600/Screen+Shot+2017-05-06+at+8.28.05+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipSic4ATQbM3XDxpkY9KtnXj7jCf7lE4BS6tiXkkEF4t0y3DUuiB57Z5AMcjCGrEtmuXNjQA1WLviDdMQKICuL7Y3MA_oDQinY7Ezj9FPVzpcutS1DNcsm6aTS25OoU7XCETCY6s4ZUjQ/s400/Screen+Shot+2017-05-06+at+8.28.05+PM.png" width="251" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style="line-height: 100%; margin-bottom: 0in;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="line-height: 100%; margin-bottom: 0in;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;b&gt;&lt;span style="font-size: large;"&gt;Buat Layout&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Pertama kali kita membuat layout terlebih dahulu. Di sini kita akan membuat dua buah layout diantaranya :

&lt;br /&gt;
&lt;br /&gt;
1. activity_login.xml&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdhxgNyBl89BkYssJdH1AO862USLqyfeFzcm8u6u5d2glC7eKjb7C8HrK3pAtG7mpkov5c3GQylkgcyL8XuNh-SCUQ23VeNN4ZtchbLLgXzPjjlNLPzHJtjF_dlRWyjW94w4YxhldhBLE/s1600/Screen+Shot+2017-05-06+at+7.54.51+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdhxgNyBl89BkYssJdH1AO862USLqyfeFzcm8u6u5d2glC7eKjb7C8HrK3pAtG7mpkov5c3GQylkgcyL8XuNh-SCUQ23VeNN4ZtchbLLgXzPjjlNLPzHJtjF_dlRWyjW94w4YxhldhBLE/s400/Screen+Shot+2017-05-06+at+7.54.51+PM.png" width="308" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="@dimen/activity_vertical_margin"&amp;gt;

    &amp;lt;LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true"
        android:padding="@dimen/activity_horizontal_margin"&amp;gt;

        &amp;lt;EditText
            android:id="@+id/et_email"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="@string/email_hint"
            android:inputType="textEmailAddress" /&amp;gt;

        &amp;lt;EditText
            android:id="@+id/et_password"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="@string/password_hint"
            android:inputType="textPassword" /&amp;gt;

    &amp;lt;/LinearLayout&amp;gt;

    &amp;lt;Button
        android:text="@string/login"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="loginAct"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true" /&amp;gt;

&amp;lt;/RelativeLayout&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
2. activity_main.xml&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicIYqPIRCoqLhXANEVH5R9pGJ7h7a0CwO9YR2IKZUKsz0Os6AyjgX28R8oh7dzxxDlz8dn4TyM-kjQagYt22HSmqUk_rOtq7aH11muDqbPP3gnGaFx4OEROfYSSR0lt2umT2GmaPZYxGo/s1600/Screen+Shot+2017-05-06+at+8.03.05+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicIYqPIRCoqLhXANEVH5R9pGJ7h7a0CwO9YR2IKZUKsz0Os6AyjgX28R8oh7dzxxDlz8dn4TyM-kjQagYt22HSmqUk_rOtq7aH11muDqbPP3gnGaFx4OEROfYSSR0lt2umT2GmaPZYxGo/s400/Screen+Shot+2017-05-06+at+8.03.05+PM.png" width="308" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.wimsonevel.androidmvp.MainActivity"&amp;gt;

    &amp;lt;TextView
        android:id="@+id/tv_welcome"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/welcome"
        android:textSize="24sp" /&amp;gt;

    &amp;lt;TextView
        android:id="@+id/tv_email"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/tv_welcome"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_marginTop="12dp" /&amp;gt;

&amp;lt;/RelativeLayout&amp;gt;

&lt;/pre&gt;
Selanjutnya kita akan membuat kerangka &lt;b&gt;Model-View-Presenter&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style="font-size: large;"&gt;Model&lt;/span&gt;&amp;nbsp;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Buat package dengan nama &lt;b&gt;model&lt;/b&gt;, kemudian buat kelas java dengan nama &lt;b&gt;User.java&lt;/b&gt;
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package com.wimsonevel.androidmvp.model;

import android.os.Parcel;
import android.os.Parcelable;

/**
 * Created by Wim on 12/31/16.
 */

public class User implements Parcelable {

    private String email;

    public User(String email) {
        this.email = email;
    }

    protected User(Parcel in) {
        this.email = in.readString();
    }

    public static final Parcelable.Creator&amp;lt;User&amp;gt; CREATOR = new Parcelable.Creator&amp;lt;User&amp;gt;() {
        @Override
        public User createFromParcel(Parcel source) {
            return new User(source);
        }

        @Override
        public User[] newArray(int size) {
            return new User[size];
        }
    };

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(this.email);
    }

}

&lt;/pre&gt;
&lt;b&gt;&lt;span style="font-size: large;"&gt;View&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Buat package dengan nama &lt;b&gt;view&lt;/b&gt;, kemudian buat beberapa interface view berikut :
&lt;br /&gt;
BaseView.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package com.wimsonevel.androidmvp.view;

import android.content.Context;

/**
 * Created by Wim on 12/31/16.
 */

public interface BaseView {

    Context getContext();

}
&lt;/pre&gt;
LoginView.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package com.wimsonevel.androidmvp.view;

import com.wimsonevel.androidmvp.model.User;

/**
 * Created by Wim on 1/1/17.
 */

public interface LoginView extends BaseView {

    void onSuccess(User user);
    void onFailed(String msg);

    void showProgress();
    void hideProgress();
}
&lt;/pre&gt;
&lt;b&gt;&lt;span style="font-size: large;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;
&lt;b&gt;&lt;span style="font-size: large;"&gt;Presenter&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Buat package dengan nama &lt;b&gt;presenter&lt;/b&gt;, kemudian buat beberapa kelas &lt;b&gt;presenter&lt;/b&gt; berikut :
&lt;br /&gt;
BasePresenter.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package com.wimsonevel.androidmvp.presenter;

/**
 * Created by Wim on 12/31/16.
 */

public interface BasePresenter&amp;lt;V&amp;gt; {

    void attachView(V view);
    void detachView();
    boolean isViewAttached();

}
&lt;/pre&gt;
LoginPresenter.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package com.wimsonevel.androidmvp.presenter;

import com.wimsonevel.androidmvp.R;
import com.wimsonevel.androidmvp.model.User;
import com.wimsonevel.androidmvp.view.LoginView;

/**
 * Created by Wim on 1/1/17.
 */

public class LoginPresenter implements BasePresenter&amp;lt;LoginView&amp;gt; {

    private LoginView loginView;

    @Override
    public void attachView(LoginView view) {
        this.loginView = view;
    }

    @Override
    public void detachView() {
        this.loginView = null;
    }

    @Override
    public boolean isViewAttached() {
        return loginView != null;
    }

    public void doLogin(String email, String password) {
        loginView.showProgress();

        if(email.equals("example@mail.com") &amp;amp;&amp;amp; password.equals("wim")) {
            loginView.hideProgress();
            loginView.onSuccess(new User(email));
        }else{
            loginView.hideProgress();
            loginView.onFailed(loginView.getContext().getResources().getString(R.string.login_failed));
        }

    }
}

&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style="font-size: large;"&gt;Activity&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Selanjutnya adalah membuat beberapa &lt;b&gt;activity&lt;/b&gt; sebagai berikut :
&lt;br /&gt;
LoginActivity.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package com.wimsonevel.androidmvp;

import android.app.ProgressDialog;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

import com.wimsonevel.androidmvp.model.User;
import com.wimsonevel.androidmvp.presenter.LoginPresenter;
import com.wimsonevel.androidmvp.view.LoginView;

import static android.text.TextUtils.isEmpty;

/**
 * Created by Wim on 1/1/17.
 */

public class LoginActivity extends AppCompatActivity implements LoginView {

    private EditText etEmail;
    private EditText etPassword;

    private LoginPresenter loginPresenter;
    private ProgressDialog progressDialog;

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

        etEmail = (EditText) findViewById(R.id.et_email);
        etPassword = (EditText) findViewById(R.id.et_password);

        progressDialog = new ProgressDialog(this);
        progressDialog.setMessage(this.getResources().getString(R.string.loading));
    }

    void loginAct(View view) {
        loginPresenter = new LoginPresenter();
        loginPresenter.attachView(this);

        if(isEmpty(etEmail.getText().toString())) {
            return;
        }

        if(isEmpty(etPassword.getText().toString())) {
            return;
        }

        if(loginPresenter.isViewAttached()) {
            loginPresenter.doLogin(etEmail.getText().toString(), etPassword.getText().toString());
        }

    }

    @Override
    public void onSuccess(User user) {
        Toast.makeText(this, this.getResources().getString(R.string.login_success), Toast.LENGTH_SHORT).show();
        MainActivity.start(this, user);
    }

    @Override
    public void onFailed(String msg) {
        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void showProgress() {
        progressDialog.show();
    }

    @Override
    public void hideProgress() {
        progressDialog.dismiss();
    }

    @Override
    public Context getContext() {
        return this;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        loginPresenter.detachView();
    }
}

&lt;/pre&gt;
MainActivity.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package com.wimsonevel.androidmvp;

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

import com.wimsonevel.androidmvp.model.User;

public class MainActivity extends AppCompatActivity {

    private TextView tvEmail;

    public static void start(Context context, User user) {
        Intent intent = new Intent(context, MainActivity.class);
        intent.putExtra(MainActivity.class.getSimpleName(), user);
        context.startActivity(intent);
    }

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

        tvEmail = (TextView) findViewById(R.id.tv_email);

        User user = getIntent().getParcelableExtra(MainActivity.class.getSimpleName());
        tvEmail.setText(user.getEmail());
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }
}
&lt;/pre&gt;
Terakhir beberapa tambahan resource string di &lt;b&gt;strings.xml&lt;/b&gt;
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;resources&amp;gt;
    &amp;lt;string name="app_name"&amp;gt;Android-MVP-Pattern&amp;lt;/string&amp;gt;

    &amp;lt;string name="email_hint"&amp;gt;Email&amp;lt;/string&amp;gt;
    &amp;lt;string name="password_hint"&amp;gt;Password&amp;lt;/string&amp;gt;
    &amp;lt;string name="login"&amp;gt;Login&amp;lt;/string&amp;gt;
    &amp;lt;string name="welcome"&amp;gt;Welcome&amp;lt;/string&amp;gt;
    &amp;lt;string name="login_success"&amp;gt;Login Success!&amp;lt;/string&amp;gt;
    &amp;lt;string name="login_failed"&amp;gt;Incorrect username or password!&amp;lt;/string&amp;gt;
    &amp;lt;string name="loading"&amp;gt;Loading...&amp;lt;/string&amp;gt;

&amp;lt;/resources&amp;gt;

&lt;/pre&gt;
Build dan running maka hasilnya seperti berikut :&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiI7o7gsvl3doBlyGik-h9P3lT4GTLd_hhfUw5meEHhJKWuMfE33diqYKixLtfyBvpUf2Rt1yqMRcyfMBDrkJlYEIGvQG8veJ3y03EjD-x1IbqoR5n6VTbgOTZUs1T47RlWX7-w8ehNsqQ/s1600/Screenshot_1494083300.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiI7o7gsvl3doBlyGik-h9P3lT4GTLd_hhfUw5meEHhJKWuMfE33diqYKixLtfyBvpUf2Rt1yqMRcyfMBDrkJlYEIGvQG8veJ3y03EjD-x1IbqoR5n6VTbgOTZUs1T47RlWX7-w8ehNsqQ/s400/Screenshot_1494083300.png" width="225" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkKGOW0Dk8xrhF1RoQ6n3dIVwBmUOci1B3V-hCIZcgj3PbilUyFD7PgD24_NZEd-tXAvkUNlEbHzkSRYspW8tCTvP7OXM1dWLhoeiXRs7w97VMCCpAUpB37I8vUd2PoZ_EUX1ecrGPCJA/s1600/Screenshot_1494083311.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkKGOW0Dk8xrhF1RoQ6n3dIVwBmUOci1B3V-hCIZcgj3PbilUyFD7PgD24_NZEd-tXAvkUNlEbHzkSRYspW8tCTvP7OXM1dWLhoeiXRs7w97VMCCpAUpB37I8vUd2PoZ_EUX1ecrGPCJA/s400/Screenshot_1494083311.png" width="225" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Source code lengkap dapat di download di&amp;nbsp;&lt;a href="https://github.com/wimsonevel/Android-MVP-Pattern"&gt;https://github.com/wimsonevel/Android-MVP-Pattern&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Sekian tutorial kali ini.&lt;br /&gt;
Semoga bermanfaat :)</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLgm_7x0NCYKPtiJjRfDuwY1lfCBfoNvfEGWb4sy4LrpJaXwwAE21R_ABmnLeei4W4OJploLHR74o5zvMbE4xMgIwGzHpHCnuRkOfvbvgyNhwp2pZNjkj34b0RlaIubk5d7GALSXKhcok/s72-c/android+mvp.png" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>(Tutorial Android) Bottom NavigationView Android Material Design</title><link>http://wimsonevel.blogspot.com/2016/12/tutorial-android-bottom-navigationview.html</link><category>Android</category><author>noreply@blogger.com (Wim Sonevel)</author><pubDate>Tue, 13 Dec 2016 15:36:00 +0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-6966757688576433754.post-7990680686305769145</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHeBQJz1K0tUjYKWKdLWaNSlvLOqcacoIROIkIX3Psv_ciEv1HKN1ZVgovEDE2lKr_u8Xx0ZLEUjqp2TMaQFFMBITvBjAigUjb1gozC6Xlc3fcPPyTqQPA3AptiRy71uMJ6noqut3tODo/s1600/android-bottomnavigation.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHeBQJz1K0tUjYKWKdLWaNSlvLOqcacoIROIkIX3Psv_ciEv1HKN1ZVgovEDE2lKr_u8Xx0ZLEUjqp2TMaQFFMBITvBjAigUjb1gozC6Xlc3fcPPyTqQPA3AptiRy71uMJ6noqut3tODo/s640/android-bottomnavigation.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;b&gt;Bottom Navigation&lt;/b&gt; adalah fitur yang baru-baru ini ditambahkan di Android &lt;b&gt;Design Support versi 25&lt;/b&gt;. Bottom Navigation dapat memudahkan kita membuat desain dengan menu tab bar berada di bawah (hampir sama seperti bottom tabs di iOS). Jika sebelumnya kita membuat bottom bar memakai tambahan library third party, kini Bottom Navigation sudah tersedia di Design Support dan siap diimplementasikan di aplikasi kita. &lt;br /&gt;
&lt;br /&gt;
Pada tutorial kali ini saya akan membahas implementasi dari Bottom &lt;b&gt;NavigationView&lt;/b&gt;.&lt;br /&gt;
Pertama-tama kita tambahkan dulu design support library versi 25 di gradle.

&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:25.0.0'
    compile 'com.android.support:design:25.0.0'
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Membuat Layout
&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Buat sebuah layout &lt;b&gt;activity_main.xml&lt;/b&gt; dan tambahkan Bottom Navigation View di dalamnya. Karena Bottom Navigation ini letaknya harus di bawah, maka kita harus mendefinisikan letaknya dengan atribut &lt;b&gt;layout_alignParentBottom="true"&lt;/b&gt;. 
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.wimso.androidbottomnavigation.MainActivity"&amp;gt;

    &amp;lt;FrameLayout
        android:id="@+id/flContent"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/bottom_navigation" /&amp;gt;

    &amp;lt;android.support.design.widget.BottomNavigationView
        android:id="@+id/bottom_navigation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        app:itemBackground="@color/colorPrimary"
        app:itemIconTint="@color/colorWhite"
        app:itemTextColor="@color/colorWhite"
        app:menu="@menu/bottom_menu"/&amp;gt;

&amp;lt;/RelativeLayout&amp;gt;
&lt;/pre&gt;
Beberapa atribut yang ada di Bottom Navigation :&lt;br /&gt;
- &lt;b&gt;app:itemBackground&lt;/b&gt; - Warna background pada bottom navigation menu&lt;br /&gt;
- &lt;b&gt;app:itemIconTint&lt;/b&gt; -Tint yang dapat digunakan pada icon menu&lt;br /&gt;
- &lt;b&gt;app:itemTextColor&lt;/b&gt; – Warna text pada bottom navigation menu&lt;br /&gt;
- &lt;b&gt;app:menu&lt;/b&gt; – resource menu untuk menampilkan item pada bottom navigation menu
&lt;br /&gt;
&lt;br /&gt;
Kemudian buat beberapa layout lagi untuk menu-menu di Bottom Navigation.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;fragment_home.xml
&lt;/b&gt;&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"&amp;gt;

    &amp;lt;TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="@string/home"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true" /&amp;gt;

&amp;lt;/RelativeLayout&amp;gt;
&lt;/pre&gt;
&lt;b&gt;fragment_notification.xml
&lt;/b&gt;&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"&amp;gt;

    &amp;lt;TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="@string/notifications"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true" /&amp;gt;

&amp;lt;/RelativeLayout&amp;gt;
&lt;/pre&gt;
&lt;b&gt;fragment_favorites.xml
&lt;/b&gt;&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"&amp;gt;

    &amp;lt;TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="@string/favorites"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true" /&amp;gt;

&amp;lt;/RelativeLayout&amp;gt;
&lt;/pre&gt;
&lt;b&gt;fragment_search.xml
&lt;/b&gt;&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"&amp;gt;

    &amp;lt;TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="@string/search"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true" /&amp;gt;

&amp;lt;/RelativeLayout&amp;gt;
&lt;/pre&gt;
&lt;b&gt;fragment_profile.xml
&lt;/b&gt;&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"&amp;gt;

    &amp;lt;TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="@string/profile"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true" /&amp;gt;

&amp;lt;/RelativeLayout&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
Tambahkan beberapa resources.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;strings.xml
&lt;/b&gt;&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;resources&amp;gt;
    &amp;lt;string name="app_name"&amp;gt;AndroidBottomNavigation&amp;lt;/string&amp;gt;

    &amp;lt;string name="home"&amp;gt;Home&amp;lt;/string&amp;gt;
    &amp;lt;string name="notifications"&amp;gt;Notifications&amp;lt;/string&amp;gt;
    &amp;lt;string name="favorites"&amp;gt;Favorites&amp;lt;/string&amp;gt;
    &amp;lt;string name="search"&amp;gt;Search&amp;lt;/string&amp;gt;
    &amp;lt;string name="profile"&amp;gt;Profile&amp;lt;/string&amp;gt;

&amp;lt;/resources&amp;gt;
&lt;/pre&gt;
&lt;b&gt;colors.xml
&lt;/b&gt;&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;resources&amp;gt;
    &amp;lt;color name="colorPrimary"&amp;gt;#F44336&amp;lt;/color&amp;gt;
    &amp;lt;color name="colorPrimaryDark"&amp;gt;#E53935&amp;lt;/color&amp;gt;
    &amp;lt;color name="colorAccent"&amp;gt;#FF4081&amp;lt;/color&amp;gt;
    &amp;lt;color name="colorWhite"&amp;gt;#FFFFFF&amp;lt;/color&amp;gt;
&amp;lt;/resources&amp;gt;

&lt;/pre&gt;
&lt;br /&gt;
Buat beberapa fragment untuk setiap menu bottom navigation.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;HomeFragment.java
&lt;/b&gt;&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.wimso.androidbottomnavigation.R;

/**
 * Created by Wim on 11/30/16.
 */
public class HomeFragment extends Fragment {

    public static HomeFragment newInstance() {
        return new HomeFragment();
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_home, container, false);
        return view;
    }
    
}

&lt;/pre&gt;
&lt;b&gt;NotificationFragment.java
&lt;/b&gt;&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.wimso.androidbottomnavigation.R;
/**
 * Created by Wim on 11/30/16.
 */
public class NotificationFragment extends Fragment {
    public static NotificationFragment newInstance() {
        return new NotificationFragment();
    }
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_notification, container, false);
        return view;
    }
}
&lt;/pre&gt;
&lt;b&gt;FavoritesFragment.java
&lt;/b&gt;&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.wimso.androidbottomnavigation.R;
/**
 * Created by Wim on 11/30/16.
 */
public class FavoritesFragment extends Fragment {

    public static FavoritesFragment newInstance() {
        return new FavoritesFragment();
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_favorites, container, false);
        return view;
    }

}
&lt;/pre&gt;
&lt;b&gt;SearchFragment.java
&lt;/b&gt;&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.wimso.androidbottomnavigation.R;
/**
 * Created by Wim on 11/30/16.
 */
public class SearchFragment extends Fragment {

    public static SearchFragment newInstance() {
        return new SearchFragment();
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_search, container, false);
        return view;
    }

}
&lt;/pre&gt;
&lt;b&gt;ProfileFragment.java
&lt;/b&gt;&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.wimso.androidbottomnavigation.R;
/**
 * Created by Wim on 11/30/16.
 */
public class ProfileFragment extends Fragment {

    public static ProfileFragment newInstance() {
        return new ProfileFragment();
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_profile, container, false);
        return view;
    }

}
&lt;/pre&gt;
Selanjutnya buat &lt;b&gt;MainActivity&lt;/b&gt; dan lengkapi code berikut :&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import android.support.annotation.NonNull;
import android.support.design.widget.BottomNavigationView;
import android.support.v4.app.Fragment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MenuItem;
import com.wimso.androidbottomnavigation.fragment.FavoritesFragment;
import com.wimso.androidbottomnavigation.fragment.HomeFragment;
import com.wimso.androidbottomnavigation.fragment.NotificationFragment;
import com.wimso.androidbottomnavigation.fragment.ProfileFragment;
import com.wimso.androidbottomnavigation.fragment.SearchFragment;

public class MainActivity extends AppCompatActivity implements BottomNavigationView.OnNavigationItemSelectedListener {

    BottomNavigationView bottomNavigationView;

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

        if(savedInstanceState == null) {
            getSupportFragmentManager()
                    .beginTransaction()
                    .replace(R.id.flContent, HomeFragment.newInstance())
                    .commit();
        }

        bottomNavigationView = (BottomNavigationView) findViewById(R.id.bottom_navigation);
        bottomNavigationView.setOnNavigationItemSelectedListener(this);
    }

    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        Fragment fragment = null;

        switch (item.getItemId()) {
            case R.id.action_home:
                fragment = HomeFragment.newInstance();
                break;
            case R.id.action_notifications:
                fragment = NotificationFragment.newInstance();
                break;
            case R.id.action_favorites:
                fragment = FavoritesFragment.newInstance();
                break;
            case R.id.action_search:
                fragment = SearchFragment.newInstance();
                break;
            case R.id.action_profile:
                fragment = ProfileFragment.newInstance();
                break;
        }

        getSupportFragmentManager()
                .beginTransaction()
                .replace(R.id.flContent, fragment)
                .commit();

        return false;
    }

}
&lt;/pre&gt;
Build dan jalankan hasilnya akan tampak sebagai berikut :&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiutv_qRYijzCrri9Fss2frVkluD80rEm5eeMDDCqYcIfE3LveMGzl-X_WGyzv4AXc1-SmkaT40bn1Ez84j9MPEUp4T_c7MDZhXK5PXJ8dvAWsVKRfYnaDohSntg_iDvDxPfoKd4QtAjcU/s1600/Screenshot_1480579931.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiutv_qRYijzCrri9Fss2frVkluD80rEm5eeMDDCqYcIfE3LveMGzl-X_WGyzv4AXc1-SmkaT40bn1Ez84j9MPEUp4T_c7MDZhXK5PXJ8dvAWsVKRfYnaDohSntg_iDvDxPfoKd4QtAjcU/s400/Screenshot_1480579931.png" width="225" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Source code lengkap dapat dilihat di &lt;a href="https://github.com/wimsonevel/AndroidBottomNavigation"&gt;https://github.com/wimsonevel/AndroidBottomNavigation&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Sekian tutorial kali ini, semoga bermanfaat.&lt;br /&gt;
Terima kasih :)</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHeBQJz1K0tUjYKWKdLWaNSlvLOqcacoIROIkIX3Psv_ciEv1HKN1ZVgovEDE2lKr_u8Xx0ZLEUjqp2TMaQFFMBITvBjAigUjb1gozC6Xlc3fcPPyTqQPA3AptiRy71uMJ6noqut3tODo/s72-c/android-bottomnavigation.png" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">7</thr:total></item><item><title>(Tutorial Android) Upload Image using Retrofit</title><link>http://wimsonevel.blogspot.com/2016/11/tutorial-android-upload-image-using.html</link><category>Android</category><author>noreply@blogger.com (Wim Sonevel)</author><pubDate>Wed, 16 Nov 2016 14:55:00 +0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-6966757688576433754.post-5467386719810386055</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9wzl2HjRYhGmk3F14Zr3-eWnIebfLhvWXQvhdcTnLurxuwQobL-bnBiDXGMzID4kKggbuE_dtPbPeU7C2zT2TiYibpIENN_av8ySh-CbRmkaTNTr2e9EH6dI7JzZNv0COPtoPy7qmqF8/s1600/android-uploadimage.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9wzl2HjRYhGmk3F14Zr3-eWnIebfLhvWXQvhdcTnLurxuwQobL-bnBiDXGMzID4kKggbuE_dtPbPeU7C2zT2TiYibpIENN_av8ySh-CbRmkaTNTr2e9EH6dI7JzZNv0COPtoPy7qmqF8/s640/android-uploadimage.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Upload file atau image dari Android ke server bisa dilakukan dengan berbagai macam cara, salah satunya menggunakan library &lt;b&gt;retrofit&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
Pada postingan kali ini saya akan memberikan tutorial upload image menggunakan &lt;b&gt;retrofit&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
Pada kasus kali ini kita akan mencoba mengupload image dengan dua metode yakni :&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;1. Multipart&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;2. Base64&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Saya akan sedikit menjelaskan metode upload image dengan &lt;b&gt;multipart&lt;/b&gt; maupun &lt;b&gt;base64&lt;/b&gt; tersebut.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Multipart&lt;/b&gt; : Metode yang menggunakan HTTP Request untuk mengirim data ke server. Metode ini biasanya digunakan untuk mengupload file yang sizenya besar.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Base64&lt;/b&gt; :  Metode yang digunakan untuk melakukan proses encoding terhadap suatu binary data (contohnya: image). Proses encoding tersebut akan menghasilkan format string. Nah, format string inilah nantinya yang akan dikirim ke server dan dilakukan proses decode untuk mengembalikannya ke binary.&lt;br /&gt;
&lt;br /&gt;
Oke mari kita langsung praktek saja.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Buat API&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
- Pertama buat folder di htdocs dengan nama &lt;b&gt;api&lt;/b&gt;&lt;br /&gt;
- Buat file php dengan nama &lt;b&gt;upload.php&lt;/b&gt;, kemudian isikan code berikut :
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?php
 $action = htmlspecialchars($_POST['action']);

 $response = array("success" =&amp;gt; FALSE);

 if($action == "multipart") {
     if ($_FILES["photo"]["error"] &amp;gt; 0) {
      $response["success"] = FALSE;
   $response["message"] = "Upload Failed";
     } else {
   $name_file=htmlspecialchars($_FILES['photo']['name']);
   
         if (@getimagesize($_FILES["photo"]["tmp_name"]) !== false) {

    move_uploaded_file($_FILES["photo"]["tmp_name"], $name_file);

    $response["success"] = TRUE;
       $response["message"] = "Upload Successfull";
    
   }else{
    $response["success"] = FALSE;
    $response["message"] = "Upload Failed";
   }

   echo json_encode($response);
     }
 }else if($action == "base64") {
  $photo = htmlspecialchars($_POST['photo']);

  $photo = str_replace('data:image/png;base64,', '', $photo);
  $photo = str_replace(' ', '+', $photo);

  $data = base64_decode($photo);
  $file = uniqid() . '.png';

  file_put_contents($file, $data);

  $response["success"] = TRUE;
  $response["message"] = "Upload Successfull";
  
  echo json_encode($response);
 }

?&amp;gt;
&lt;/pre&gt;
&lt;span style="font-size: large;"&gt;Buat Project Android&lt;/span&gt;
&lt;br /&gt;
&lt;br /&gt;
Pertama, tambahkan library retrofit dan okhttp3 ke gradle module-level
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:24.2.1'

    // Network
    compile 'com.squareup.retrofit2:retrofit:2.1.0'
    compile 'com.squareup.retrofit2:converter-gson:2.1.0'
    compile "com.squareup.okhttp3:okhttp:3.4.1"
    compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'
}

&lt;/pre&gt;
Buat layout dengan nama &lt;b&gt;activity_main.xml &lt;/b&gt;
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.wimso.android_uploadimage.MainActivity"&amp;gt;

    &amp;lt;Button
        android:id="@+id/btn_choose"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Choose Photo"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" /&amp;gt;

    &amp;lt;ImageView
        android:id="@+id/img_thumb"
        android:layout_width="match_parent"
        android:layout_height="250dp"
        android:layout_below="@+id/btn_choose"
        android:src="@mipmap/ic_launcher"
        android:scaleType="centerCrop"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" /&amp;gt;

    &amp;lt;Button
        android:id="@+id/btn_upload_1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Upload with Multipart"
        android:layout_below="@+id/img_thumb"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" /&amp;gt;

    &amp;lt;Button
        android:id="@+id/btn_upload_2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Upload with Base64"
        android:layout_below="@+id/btn_upload_1"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" /&amp;gt;

&amp;lt;/RelativeLayout&amp;gt;

&lt;/pre&gt;
Buat package dengan nama &lt;b&gt;network&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
Buat kelas dengan nama &lt;b&gt;Config.java&lt;/b&gt; di package network. Kelas ini berisi &lt;b&gt;URL&lt;/b&gt; dan &lt;b&gt;Endpoint&lt;/b&gt; dari API.
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;/**
 * Created by Wim on 11/14/16.
 */
public class Config {

    public static final String BASE_URL = "http://192.168.2.31"; // Your local IP Address
    public static final String API_DIR = "/api";

    public static final String API_UPLOAD = BASE_URL + API_DIR + "/upload.php";

}
&lt;/pre&gt;
Kemudian buat kelas dengan nama &lt;b&gt;BaseResponse.java
&lt;/b&gt;&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;/**
 * Created by Wim on 11/14/16.
 */
public class BaseResponse {

    private boolean success;
    private String message;

    public boolean isSuccess() {
        return success;
    }

    public void setSuccess(boolean success) {
        this.success = success;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

&lt;/pre&gt;
Kemudian buat sebuah interface dengan nama &lt;b&gt;UploadInterface.java&lt;/b&gt; yang berisi method untuk mengupload image ke server. Method untuk mengupload image terdiri dari 2 yakni method dengan teknik multipart dan base46.
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import retrofit2.Call;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.Multipart;
import retrofit2.http.POST;
import retrofit2.http.Part;

/**
 * Created by Wim on 10/6/16.
 */
public interface UploadInterface {

    @Multipart
    @POST(Config.API_UPLOAD)
    Call&amp;lt;BaseResponse&amp;gt; uploadPhotoMultipart(
            @Part("action") RequestBody action,
            @Part MultipartBody.Part photo);

    @FormUrlEncoded
    @POST(Config.API_UPLOAD)
    Call&amp;lt;BaseResponse&amp;gt; uploadPhotoBase64(
            @Field("action") String action,
            @Field("photo") String photo);

}

&lt;/pre&gt;
Kemudian buat kelas&lt;b&gt; UploadService.java&lt;/b&gt; untuk konfigurasi retrofit dan method dari interface.
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;/**
 * Created by Wim on 10/7/16.
 */
public class UploadService {

    private UploadInterface uploadInterface;

    public UploadService() {
        OkHttpClient.Builder okhttpBuilder = new OkHttpClient().newBuilder();
        okhttpBuilder.connectTimeout(60, TimeUnit.SECONDS);
        okhttpBuilder.writeTimeout(60, TimeUnit.SECONDS);
        okhttpBuilder.readTimeout(60, TimeUnit.SECONDS);
        okhttpBuilder.retryOnConnectionFailure(true);

        if (BuildConfig.DEBUG) {
            HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
            interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
            okhttpBuilder.addInterceptor(interceptor);
        }

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(Config.BASE_URL)
                .client(okhttpBuilder.build())
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        uploadInterface = retrofit.create(UploadInterface.class);
    }

    public void uploadPhotoMultipart(RequestBody action, MultipartBody.Part photo, Callback callback) {
        uploadInterface.uploadPhotoMultipart(action, photo).enqueue(callback);
    }

    public void uploadPhotoBase64(String action, String photo, Callback callback) {
        uploadInterface.uploadPhotoBase64(action, photo).enqueue(callback);
    }

}

&lt;/pre&gt;
Selanjutnya buat beberapa kelas utility berikut :&lt;br /&gt;
&lt;br /&gt;
FileUtils.java&lt;br /&gt;
(Kelas ini saya modifikasi dari &lt;a href="https://github.com/iPaulPro/aFileChooser/blob/master/aFileChooser/src/com/ipaulpro/afilechooser/utils/FileUtils.java"&gt;https://github.com/iPaulPro/aFileChooser/blob/master/aFileChooser/src/com/ipaulpro/afilechooser/utils/FileUtils.java&lt;/a&gt;&amp;nbsp;)
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import android.content.ContentUris;
import android.content.Context;
import android.content.CursorLoader;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

/**
 * Created by Wim on 9/29/16.
 */
public class FileUtils {

    /**
     * @return Whether the URI is a local one.
     */
    public static boolean isLocal(String url) {
        if (url != null &amp;amp;&amp;amp; !url.startsWith("http://") &amp;amp;&amp;amp; !url.startsWith("https://")) {
            return true;
        }
        return false;
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is ExternalStorageProvider.
     * @author paulburke
     */
    public static boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is DownloadsProvider.
     * @author paulburke
     */
    public static boolean isDownloadsDocument(Uri uri) {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is MediaProvider.
     * @author paulburke
     */
    public static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is Old Google Photos.
     */
    public static boolean isGoogleOldPhotosUri(Uri uri) {
        return "com.google.android.apps.photos.content".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is New Google Photos.
     */
    public static boolean isGoogleNewPhotosUri(Uri uri) {
        return "com.google.android.apps.photos.contentprovider".equals(uri.getAuthority());
    }

    public static String getDataColumn(Context context, Uri uri, String selection,
                                       String[] selectionArgs) {

        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = {
                column
        };

        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                    null);
            if (cursor != null &amp;amp;&amp;amp; cursor.moveToFirst()) {
                final int column_index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(column_index);
            }
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
    }

    public static String getPath(final Context context, final Uri uri) {
        // DocumentProvider
        if (Build.VERSION.SDK_INT &amp;gt;= Build.VERSION_CODES.KITKAT) {
            if(DocumentsContract.isDocumentUri(context, uri)) {
                // ExternalStorageProvider
                if (isExternalStorageDocument(uri)) {
                    final String docId = DocumentsContract.getDocumentId(uri);
                    final String[] split = docId.split(":");
                    final String type = split[0];

                    if ("primary".equalsIgnoreCase(type)) {
                        return Environment.getExternalStorageDirectory() + "/" + split[1];
                    }

                    // TODO handle non-primary volumes
                }
                // DownloadsProvider
                else if (isDownloadsDocument(uri)) {

                    final String id = DocumentsContract.getDocumentId(uri);
                    final Uri contentUri = ContentUris.withAppendedId(
                            Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

                    return getDataColumn(context, contentUri, null, null);
                }
                // MediaProvider
                else if (isMediaDocument(uri)) {
                    final String docId = DocumentsContract.getDocumentId(uri);
                    final String[] split = docId.split(":");
                    final String type = split[0];

                    Uri contentUri = null;
                    if ("image".equals(type)) {
                        contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                    }

                    final String selection = "_id=?";
                    final String[] selectionArgs = new String[]{
                            split[1]
                    };

                    return getDataColumn(context, contentUri, selection, selectionArgs);
                }
            }
            // MediaStore (and general)
            else if ("content".equalsIgnoreCase(uri.getScheme())) {

                // Return the remote address
                if (isGoogleOldPhotosUri(uri)) {
                    // return http path, then download file.
                    return uri.getLastPathSegment();
                }
                else if (isGoogleNewPhotosUri(uri)) {
                    if(getDataColumn(context,  uri, null, null) == null) {
                        return getDataColumn(context,  Uri.parse(getImageUrlWithAuthority(context,uri)), null, null);
                    }else{
                        return getDataColumn(context,  uri, null, null);
                    }
                }

                return getDataColumn(context, uri, null, null);
            }
            // File
            else if ("file".equalsIgnoreCase(uri.getScheme())) {
                return uri.getPath();
            }
        }else{
            String[] proj = { MediaStore.Images.Media.DATA };
            String result = null;

            CursorLoader cursorLoader = new CursorLoader(
                    context,
                    uri, proj, null, null, null);
            Cursor cursor = cursorLoader.loadInBackground();

            if(cursor != null){
                int column_index =
                        cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                cursor.moveToFirst();
                result = cursor.getString(column_index);
            }

            return result;
        }


        return null;
    }

    public static File getFile(Context context, Uri uri) {
        if (uri != null) {
            String path = getPath(context, uri);
            if (path != null &amp;amp;&amp;amp; isLocal(path)) {
                return new File(path);
            }
        }
        return null;
    }

    public static String getImageUrlWithAuthority(Context context, Uri uri) {
        InputStream is = null;
        if (uri.getAuthority() != null) {
            try {
                is = context.getContentResolver().openInputStream(uri);
                Bitmap bmp = BitmapFactory.decodeStream(is);

                return writeToTempImageAndGetPathUri(context, bmp).toString();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }finally {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    public static Uri writeToTempImageAndGetPathUri(Context inContext, Bitmap inImage) {
        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
        inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
        String path = MediaStore.Images.Media.insertImage(inContext.getContentResolver(), inImage, "Title", null);
        return Uri.parse(path);
    }
}
&lt;/pre&gt;
ImageUtils.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import android.graphics.Bitmap;
import android.util.Base64;

import java.io.ByteArrayOutputStream;

/**
 * Created by Wim on 11/14/16.
 */
public class ImageUtils {

    public static String bitmapToBase64String(Bitmap bmp, int quality) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bmp.compress(Bitmap.CompressFormat.JPEG, quality, baos);
        byte[] bytes = baos.toByteArray();
        return Base64.encodeToString(bytes, Base64.DEFAULT);
    }

}
&lt;/pre&gt;
Sekarang Buka &lt;b&gt;MainActivity.java&lt;/b&gt; dan lengkapi dengan kode berikut :
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.net.Uri;
import android.provider.MediaStore;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

import com.wimso.android_uploadimage.network.BaseResponse;
import com.wimso.android_uploadimage.network.UploadService;

import java.io.File;
import java.io.IOException;

import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    private static final int PICK_IMAGE = 1;
    private static final int PERMISSION_REQUEST_STORAGE = 2;

    private static final String TYPE_1 = "multipart";
    private static final String TYPE_2 = "base64";

    private ImageView imgThumb;

    private Button btnChoose;
    private Button btnUpload1;
    private Button btnUpload2;

    private UploadService uploadService;
    private Uri uri;

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

        imgThumb = (ImageView) findViewById(R.id.img_thumb);
        btnChoose = (Button) findViewById(R.id.btn_choose);
        btnUpload1 = (Button) findViewById(R.id.btn_upload_1);
        btnUpload2 = (Button) findViewById(R.id.btn_upload_2);

        btnChoose.setOnClickListener(this);
        btnUpload1.setOnClickListener(this);
        btnUpload2.setOnClickListener(this);
    }

    private void choosePhoto() {
        if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.READ_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED
                &amp;amp;&amp;amp; ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {

            ActivityCompat.requestPermissions(this,
                    new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE, android.Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    PERMISSION_REQUEST_STORAGE);

        }else{
            openGallery();
        }
    }

    public void openGallery() {
        Intent intent = new Intent();
        intent.setType("image/*");
        intent.setAction(Intent.ACTION_GET_CONTENT);
        startActivityForResult(Intent.createChooser(intent, "Select Image"), PICK_IMAGE);
    }

    @Override
    public void onClick(View view) {
        if(view == btnChoose) {
            choosePhoto();
        }else if(view == btnUpload1) {
            if(uri != null) {
                File file = FileUtils.getFile(this, uri);
                uploadMultipart(file);
            }else{
                Toast.makeText(this, "You must choose the image", Toast.LENGTH_SHORT).show();
            }
        }else if(view == btnUpload2) {
            if(uri != null) {
                Bitmap bitmap = null;
                try {
                    bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
                } catch (IOException e) {
                    e.printStackTrace();
                }

                String encoded = ImageUtils.bitmapToBase64String(bitmap, 100);
                uploadBase64(encoded);
            }else{
                Toast.makeText(this, "You must choose the image", Toast.LENGTH_SHORT).show();
            }
        }
    }
    private void uploadMultipart(File file) {
        RequestBody photoBody = RequestBody.create(MediaType.parse("image/*"), file);
        MultipartBody.Part photoPart = MultipartBody.Part.createFormData("photo",
                file.getName(), photoBody);

        RequestBody action = RequestBody.create(MediaType.parse("text/plain"), TYPE_1);

        uploadService = new UploadService();
        uploadService.uploadPhotoMultipart(action, photoPart, new Callback() {
            @Override
            public void onResponse(Call call, Response response) {
                BaseResponse baseResponse = (BaseResponse) response.body();

                if(baseResponse != null) {
                    Toast.makeText(MainActivity.this, baseResponse.getMessage(), Toast.LENGTH_SHORT).show();
                }
            }

            @Override
            public void onFailure(Call call, Throwable t) {
                t.printStackTrace();
            }
        });
    }

    private void uploadBase64(String imgBase64) {
        uploadService = new UploadService();
        uploadService.uploadPhotoBase64(TYPE_2, imgBase64, new Callback() {
            @Override
            public void onResponse(Call call, Response response) {
                BaseResponse baseResponse = (BaseResponse) response.body();

                if(baseResponse != null) {
                    Toast.makeText(MainActivity.this, baseResponse.getMessage(), Toast.LENGTH_SHORT).show();
                }
            }

            @Override
            public void onFailure(Call call, Throwable t) {
                t.printStackTrace();
            }
        });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == PICK_IMAGE &amp;amp;&amp;amp; resultCode == Activity.RESULT_OK) {
            if(data != null) {
                uri = data.getData();

                imgThumb.setImageURI(uri);
            }
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           String permissions[], int[] grantResults) {
        switch (requestCode) {
            case PERMISSION_REQUEST_STORAGE: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length &amp;gt; 0
                        &amp;amp;&amp;amp; grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                    openGallery();
                }

                return;
            }
        }
    }

}
&lt;/pre&gt;
Terakhir, tambahkan permission di &lt;b&gt;AndroidManifest.xml&lt;/b&gt;
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;uses-permission android:name="android.permission.INTERNET" /&amp;gt;
&amp;lt;uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/&amp;gt;
&amp;lt;uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/&amp;gt;
&lt;/pre&gt;
Build dan jalankan aplikasi kemudian coba upload image dengan 2 metode :&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhU9vxSjrJWEQ23Iq_LyxRCgn-BH0D3o9fZOFATwzBczGVZh3fqnwuTmrKYG-34f1QBp-Y9Jy2v_PH9z-ip-0sp3KIwAPD8jLcYjuE-gi-yJTZGxXulW3eFMoefVNyKYn2xLC95z_MZ3_Q/s1600/device-2016-11-16-124735.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhU9vxSjrJWEQ23Iq_LyxRCgn-BH0D3o9fZOFATwzBczGVZh3fqnwuTmrKYG-34f1QBp-Y9Jy2v_PH9z-ip-0sp3KIwAPD8jLcYjuE-gi-yJTZGxXulW3eFMoefVNyKYn2xLC95z_MZ3_Q/s640/device-2016-11-16-124735.png" width="360" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Mari kita lihat image yang sudah ter-upload :
&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKSiGbAFA6qdnpgboUQyVL96tBkDlJ9GGYz09o6uKDIMWJ1Nb3WbsRLcEtOCacqJ6XHiHpq2yM7CV76zGD_K7ZFqfbZio5ORXmPcty3NrOtgBw2CxWWN1ulDIPRfIAlE6H2fThP_0pJPU/s1600/Screen+Shot+2016-11-16+at+1.24.47+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="284" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKSiGbAFA6qdnpgboUQyVL96tBkDlJ9GGYz09o6uKDIMWJ1Nb3WbsRLcEtOCacqJ6XHiHpq2yM7CV76zGD_K7ZFqfbZio5ORXmPcty3NrOtgBw2CxWWN1ulDIPRfIAlE6H2fThP_0pJPU/s640/Screen+Shot+2016-11-16+at+1.24.47+PM.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
- Image baris &lt;b&gt;pertama&lt;/b&gt; merupakan hasil dari upload menggunakan &lt;b&gt;Base64&lt;/b&gt;.&lt;br /&gt;
- Image baris &lt;b&gt;kedua&lt;/b&gt; merupakan hasil dari upload menggunakan &lt;b&gt;Multipart&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
Dari kedua image tersebut dapat kita lihat bahwa dengan menggunakan &lt;b&gt;Base64&lt;/b&gt;, ukuran image menjadi jauh lebih besar dibandingkan dengan ukuran asli image tersebut. Sedangkan dengan menggunakan &lt;b&gt;Multipart&lt;/b&gt;, ukuran image tidak terlalu berpengaruh dari ukuran aslinya.&lt;br /&gt;
&lt;br /&gt;
Ukuran asli image sekitar &lt;b&gt;55 kb&lt;/b&gt;.
&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJ2fCtoIKrAPpcgTS81uDET3vahM25lxlOQ_emnXmmrcJo9ZIokoW4BDa0I_hRcQYf5P5RmWX5kShjeF9kfE0BHCvQTqDhBTS9kE1kL9jKvub18iGMdCL_Mews-cV_tfnPj72ysIjGm1E/s1600/device-2016-11-16-132942.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="280" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJ2fCtoIKrAPpcgTS81uDET3vahM25lxlOQ_emnXmmrcJo9ZIokoW4BDa0I_hRcQYf5P5RmWX5kShjeF9kfE0BHCvQTqDhBTS9kE1kL9jKvub18iGMdCL_Mews-cV_tfnPj72ysIjGm1E/s320/device-2016-11-16-132942.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Kesimpulannya adalah silahkan tentukan sendiri metode apa yang diinginkan sesuai dengan kebutuhan masing-masing :D&lt;br /&gt;
&lt;br /&gt;
Source code lengkap dapat dilihat di&amp;nbsp;&lt;a href="https://github.com/wimsonevel/Android-UploadImage"&gt;https://github.com/wimsonevel/Android-UploadImage&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Terima kasih dan semoga bermanfaat.&lt;br /&gt;
Happy Coding :)</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9wzl2HjRYhGmk3F14Zr3-eWnIebfLhvWXQvhdcTnLurxuwQobL-bnBiDXGMzID4kKggbuE_dtPbPeU7C2zT2TiYibpIENN_av8ySh-CbRmkaTNTr2e9EH6dI7JzZNv0COPtoPy7qmqF8/s72-c/android-uploadimage.png" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">15</thr:total></item><item><title>(Tutorial Android) Login and Registration with PHP &amp; MySQL</title><link>http://wimsonevel.blogspot.com/2016/11/tutorial-android-login-and-registration.html</link><category>Android</category><author>noreply@blogger.com (Wim Sonevel)</author><pubDate>Thu, 10 Nov 2016 16:21:00 +0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-6966757688576433754.post-6363485341364040513</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwj185x9HmhAn54EM2h_RwW08o_JogjnSVXYPpcbNbxeoGcFjqWzsD6wbAuK84pLPEzfDSdm57kUo01ajl3WKT_CzYbyUpBS-uCJ7hBRW1rZ-2Za5BkpQG9CyzszQ9jCJqaFk9CumCfdQ/s1600/android-loginandregistration.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwj185x9HmhAn54EM2h_RwW08o_JogjnSVXYPpcbNbxeoGcFjqWzsD6wbAuK84pLPEzfDSdm57kUo01ajl3WKT_CzYbyUpBS-uCJ7hBRW1rZ-2Za5BkpQG9CyzszQ9jCJqaFk9CumCfdQ/s640/android-loginandregistration.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Login dan Registrasi sangat sering kita temukan di beberapa aplikasi yang berbasis client server. Pada postingan kali ini saya akan memberikan tutorial membuat login dan registrasi di Android dengan &lt;b&gt;PHP&lt;/b&gt; &amp;amp; &lt;b&gt;MySQL&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
Untuk mengkoneksikan antara aplikasi android dengan server, kita perlu membuat &lt;b&gt;API&lt;/b&gt; (Application Programming Interface) sebagai jembatan penghubungnya. &lt;br /&gt;
&lt;br /&gt;
Setelah itu mendesain database sekaligus menginteraksikannya dengan &lt;b&gt;API&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
Sebelum kita memulai, pastikan laptop/notebook sudah terinstall &lt;b&gt;XAMPP&lt;/b&gt;. &lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;1. Install XAMPP&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Download dan install XAMPP di sini&amp;nbsp;&lt;a href="https://www.apachefriends.org/index.html"&gt;https://www.apachefriends.org/index.html&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;2. Buat Database MySQL&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Buka http://localhost/phpmyadmin kemudian buat database baru dengan nama &lt;b&gt;simple_db&lt;/b&gt;. Setelah itu buat table dengan nama &lt;b&gt;users&lt;/b&gt; yang berisi field-field berikut. &lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHSzXDxSlLzamkvVOVJAv_Iekjwv_uAGOmM8SHXKdN6Ndx1Cb0TcTu16l3JMjlTnpP9uYx2Bp38U4LhDUkbKpW_hy88CwUhhmq8klYySjq6mxvh7biK_EBNDmaA-OsT8Fypzc-8IIVUbc/s1600/Screen+Shot+2016-11-10+at+10.21.21+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="171" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHSzXDxSlLzamkvVOVJAv_Iekjwv_uAGOmM8SHXKdN6Ndx1Cb0TcTu16l3JMjlTnpP9uYx2Bp38U4LhDUkbKpW_hy88CwUhhmq8klYySjq6mxvh7biK_EBNDmaA-OsT8Fypzc-8IIVUbc/s640/Screen+Shot+2016-11-10+at+10.21.21+AM.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;3. Buat API&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Langkah selanjutnya adalah membuat API. Dalam hal ini kita membuat API menggunakan PHP 5. 
&lt;br /&gt;
&lt;br /&gt;
Buka folder &lt;b&gt;xampp&lt;/b&gt; → &lt;b&gt;htdocs&lt;/b&gt; dan buat folder dengan nama &lt;b&gt;simple_api&lt;/b&gt;. &lt;br /&gt;
&lt;br /&gt;
Di dalam folder simple_api, buat php file dengan nama &lt;b&gt;connect.php&lt;/b&gt;. &lt;br /&gt;
&lt;br /&gt;
Connect.php&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?php
     define('_HOST_NAME','localhost');
     define('_DATABASE_NAME','simple_db');
     define('_DATABASE_USER_NAME','root');
     define('_DATABASE_PASSWORD','');
 
     $MySQLiconn = new MySQLi(_HOST_NAME,_DATABASE_USER_NAME,_DATABASE_PASSWORD,_DATABASE_NAME);
  
     if($MySQLiconn-&amp;gt;connect_errno) {
       die("ERROR : -&amp;gt; ".$MySQLiconn-&amp;gt;connect_error);
     }


?&amp;gt;
&lt;/pre&gt;
Kemudian buat file &lt;b&gt;register.php&lt;/b&gt; dan include-kan &lt;b&gt;connect.php&lt;/b&gt; berikut.
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?php

include_once 'connect.php';

$response = array("error" =&amp;gt; FALSE);

if (isset($_POST['firstname']) &amp;amp;&amp;amp; isset($_POST['lastname']) &amp;amp;&amp;amp; isset($_POST['email']) &amp;amp;&amp;amp; isset($_POST['password'])) {
 $firstname = htmlspecialchars($_POST['firstname']);
 $lastname = htmlspecialchars($_POST['lastname']);
 $email = htmlspecialchar($_POST['email']);
 $password = htmlspecialchars($_POST['password']);
 
 $encrypted_password = hash("sha256", $password);// encrypted password
    
    $sql = $MySQLiconn-&amp;gt;query("SELECT email from users WHERE email = '$email'");

    if(mysqli_num_rows($sql) &amp;gt; 0) {
  $response["error"] = TRUE;
        $response["message"] = "User already existed";

        echo json_encode($response);
    }else{
     $sql = $MySQLiconn-&amp;gt;query("INSERT INTO users(firstname, lastname, email, password, created_at) VALUES('$firstname', '$lastname', '$email', '$encrypted_password', NOW())"); 

     if($sql) {
         $response["error"] = FALSE;
         $response["message"] = "Register Successfull";

   echo json_encode($response);
     } else {
      $response["error"] = TRUE;
         $response["message"] = "Register Failure";

   echo json_encode($response);
     }  
 
    }
    
}
?&amp;gt;
&lt;/pre&gt;
Kemudian buat file &lt;b&gt;login.php&lt;/b&gt; berikut :
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?php

include_once 'connect.php';

$response = array("error" =&amp;gt; FALSE);

if (isset($_POST['email']) &amp;amp;&amp;amp; isset($_POST['password'])) {
 
 $email = htmlspecialchars($_POST['email']);
 $password = htmlspecialchars($_POST['password']);

 $encrypted_password = hash("sha256", $password);// encrypted password
        
 $sql = $MySQLiconn-&amp;gt;query("SELECT * FROM users WHERE email='$email' AND password='$encrypted_password'");

 if(mysqli_num_rows($sql) &amp;gt; 0){
  while($row = $sql-&amp;gt;fetch_array()){
   $response["error"] = FALSE;
       $response["message"] = "Login Successfull";
       $response["data"]["firstname"] = $row['firstname'];
       $response["data"]["lastname"] = $row['lastname'];
       $response["data"]["email"] = $row['email'];
      }

  echo json_encode($response);
   }else{
    $response["error"] = TRUE;
     $response["message"] = "Incorrect Email or Password!";

  echo json_encode($response);
   }
}

?&amp;gt;
&lt;/pre&gt;
&lt;span style="font-size: large;"&gt;4. Buat Android Project
&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Setelah kita membuat API, berikutnya adalah membuat project baru di Android. Aplikasi yang dibuat nantinya memiliki 3 tampilan yakni &lt;b&gt;Login&lt;/b&gt;, &lt;b&gt;Registration&lt;/b&gt; dan &lt;b&gt;Dashboard&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
Pertama, tambahkan library yang diperlukan di gradle. 
&lt;br /&gt;
&lt;br /&gt;
Untuk library networking kita menggunakan Retrofit 2. Penjelasan dan implementasi Retrofit 2 dalam dilihat di postingan saya sebelumnya &lt;a href="http://wimsonevel.blogspot.co.id/2016/07/tutorial-android-http-client-on-android.html"&gt;http://wimsonevel.blogspot.co.id/2016/07/tutorial-android-http-client-on-android.html&lt;/a&gt;
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:24.2.1'

    compile 'com.squareup.retrofit2:retrofit:2.1.0'
    compile 'com.squareup.retrofit2:converter-gson:2.1.0'
    compile "com.squareup.okhttp3:logging-interceptor:3.3.0"
}
&lt;/pre&gt;
Buat struktur projectnya sebagai berikut :&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgakXKYMMYinRLXVov0Z5e22MHPCWydD8zePgTyzbBd-010an-EJpnpHuporOXwc1_9YQ1GplpCQjlHdVrkBk8JhV3l5WmAI2jHSBGUD2EFuzI_O9t4v171gIHTtcCSbqpbA_ERGp-mg6w/s1600/Screen+Shot+2016-11-10+at+1.10.58+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgakXKYMMYinRLXVov0Z5e22MHPCWydD8zePgTyzbBd-010an-EJpnpHuporOXwc1_9YQ1GplpCQjlHdVrkBk8JhV3l5WmAI2jHSBGUD2EFuzI_O9t4v171gIHTtcCSbqpbA_ERGp-mg6w/s400/Screen+Shot+2016-11-10+at+1.10.58+PM.png" width="282" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Edit dan tambahkan beberapa resources string di &lt;b&gt;strings.xml&lt;/b&gt; berikut :
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;resources&amp;gt;
    &amp;lt;string name="app_name"&amp;gt;AndroidLoginAndRegistration&amp;lt;/string&amp;gt;
    &amp;lt;string name="email"&amp;gt;Email&amp;lt;/string&amp;gt;
    &amp;lt;string name="password"&amp;gt;Password&amp;lt;/string&amp;gt;
    &amp;lt;string name="login"&amp;gt;Login&amp;lt;/string&amp;gt;
    &amp;lt;string name="register"&amp;gt;Register&amp;lt;/string&amp;gt;
    &amp;lt;string name="register_caption"&amp;gt;Dont have an account? Register&amp;lt;/string&amp;gt;
    &amp;lt;string name="title_activity_register"&amp;gt;RegisterActivity&amp;lt;/string&amp;gt;
    &amp;lt;string name="first_name"&amp;gt;First Name&amp;lt;/string&amp;gt;
    &amp;lt;string name="last_name"&amp;gt;Last Name&amp;lt;/string&amp;gt;
    &amp;lt;string name="logout"&amp;gt;Logout&amp;lt;/string&amp;gt;
    &amp;lt;string name="greeting"&amp;gt;Hi, %s :)&amp;lt;/string&amp;gt;
&amp;lt;/resources&amp;gt;
&lt;/pre&gt;
Edit dan tambahkan beberapa resources color di color.xml berikut :&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;resources&amp;gt;
    &amp;lt;color name="colorPrimary"&amp;gt;#2196F3&amp;lt;/color&amp;gt;
    &amp;lt;color name="colorPrimaryDark"&amp;gt;#1565C0&amp;lt;/color&amp;gt;
    &amp;lt;color name="colorAccent"&amp;gt;#1976D2&amp;lt;/color&amp;gt;
    &amp;lt;color name="colorWhite"&amp;gt;#FFFFFF&amp;lt;/color&amp;gt;
    &amp;lt;color name="colorGray"&amp;gt;#E5E5E5&amp;lt;/color&amp;gt;
    &amp;lt;color name="colorText"&amp;gt;#8A8A8A&amp;lt;/color&amp;gt;
&amp;lt;/resources&amp;gt;&lt;/pre&gt;
Edit dan tambahkan beberapa resource drawable berikut :&lt;br /&gt;
&lt;br /&gt;
btn_normal.xml
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" &amp;gt;
    &amp;lt;solid android:color="@color/colorWhite"/&amp;gt;
    &amp;lt;corners android:radius="4dp" /&amp;gt;
    &amp;lt;padding
        android:bottom="5dp"
        android:left="5dp"
        android:right="5dp"
        android:top="5dp" /&amp;gt;
&amp;lt;/shape&amp;gt;
&lt;/pre&gt;
btn_normal_2.xml
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" &amp;gt;
    &amp;lt;solid android:color="@color/colorPrimary"/&amp;gt;
    &amp;lt;corners android:radius="4dp" /&amp;gt;
    &amp;lt;padding
        android:bottom="5dp"
        android:left="5dp"
        android:right="5dp"
        android:top="5dp" /&amp;gt;
&amp;lt;/shape&amp;gt;
&lt;/pre&gt;
btn_pressed.xml
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" &amp;gt;
    &amp;lt;solid android:color="@color/colorGray"/&amp;gt;
    &amp;lt;corners android:radius="4dp" /&amp;gt;
    &amp;lt;padding
        android:bottom="5dp"
        android:left="5dp"
        android:right="5dp"
        android:top="5dp" /&amp;gt;
&amp;lt;/shape&amp;gt;
&lt;/pre&gt;
btn_pressed_2.xml
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" &amp;gt;
    &amp;lt;solid android:color="@color/colorPrimaryDark"/&amp;gt;
    &amp;lt;corners android:radius="4dp" /&amp;gt;
    &amp;lt;padding
        android:bottom="5dp"
        android:left="5dp"
        android:right="5dp"
        android:top="5dp" /&amp;gt;
&amp;lt;/shape&amp;gt;
&lt;/pre&gt;
btn_background.xml
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;selector xmlns:android="http://schemas.android.com/apk/res/android"&amp;gt;
    &amp;lt;item android:state_pressed="true"
        android:drawable="@drawable/btn_pressed" /&amp;gt; &amp;lt;!-- pressed --&amp;gt;
    &amp;lt;item android:state_focused="true"
        android:drawable="@drawable/btn_normal" /&amp;gt; &amp;lt;!-- focused --&amp;gt;
    &amp;lt;item android:drawable="@drawable/btn_normal" /&amp;gt; &amp;lt;!-- default --&amp;gt;
&amp;lt;/selector&amp;gt;
&lt;/pre&gt;
btn_background_2.xml
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;selector xmlns:android="http://schemas.android.com/apk/res/android"&amp;gt;
    &amp;lt;item android:state_pressed="true"
        android:drawable="@drawable/btn_pressed_2" /&amp;gt; &amp;lt;!-- pressed --&amp;gt;
    &amp;lt;item android:state_focused="true"
        android:drawable="@drawable/btn_normal_2" /&amp;gt; &amp;lt;!-- focused --&amp;gt;
    &amp;lt;item android:drawable="@drawable/btn_normal_2" /&amp;gt; &amp;lt;!-- default --&amp;gt;
&amp;lt;/selector&amp;gt;
&lt;/pre&gt;
Selanjutnya buat beberapa layout untuk Login, Registrasi dan Dashboard berikut :&lt;br /&gt;
&lt;br /&gt;
activity_login.xml
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:windowSoftInputMode="adjustResize"
    android:background="@color/colorPrimary"
    tools:context="com.wimso.androidloginandregistration.MainActivity"&amp;gt;

    &amp;lt;LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true"&amp;gt;

        &amp;lt;EditText
            android:id="@+id/email"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:inputType="textEmailAddress"
            android:ems="10"
            android:hint="@string/email"
            android:textColor="@color/colorWhite"
            android:textColorHint="@color/colorWhite"
            android:padding="@dimen/activity_vertical_margin"
            android:theme="@style/WhiteFocus"/&amp;gt;

        &amp;lt;EditText
            android:id="@+id/password"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:inputType="textPassword"
            android:ems="10"
            android:hint="@string/password"
            android:textColor="@color/colorWhite"
            android:textColorHint="@color/colorWhite"
            android:padding="@dimen/activity_vertical_margin"
            android:layout_marginTop="@dimen/activity_vertical_margin"
            android:theme="@style/WhiteFocus" /&amp;gt;

    &amp;lt;/LinearLayout&amp;gt;

    &amp;lt;LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"&amp;gt;

        &amp;lt;Button
            android:id="@+id/btn_login"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/login"
            android:background="@drawable/btn_background"
            android:textColor="@color/colorPrimary"/&amp;gt;

        &amp;lt;TextView
            android:id="@+id/register_caption"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:text="@string/register_caption"
            android:layout_marginTop="@dimen/activity_vertical_margin"
            android:gravity="center"
            android:textColor="@color/colorWhite" /&amp;gt;

    &amp;lt;/LinearLayout&amp;gt;

&amp;lt;/RelativeLayout&amp;gt;

&lt;/pre&gt;
activity_register.xml
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:windowSoftInputMode="adjustResize"
    android:background="@color/colorPrimary"
    tools:context="com.wimso.androidloginandregistration.RegisterActivity"&amp;gt;

    &amp;lt;android.support.v7.widget.Toolbar
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?actionBarSize"
        android:background="?colorPrimary"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" /&amp;gt;

    &amp;lt;LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true"&amp;gt;

        &amp;lt;EditText
            android:id="@+id/firstname"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:inputType="textPersonName"
            android:hint="@string/first_name"
            android:textColor="@color/colorWhite"
            android:textColorHint="@color/colorWhite"
            android:ems="10"
            android:padding="@dimen/activity_vertical_margin"
            android:theme="@style/WhiteFocus" /&amp;gt;

        &amp;lt;EditText
            android:id="@+id/lastname"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:inputType="textPersonName"
            android:hint="@string/last_name"
            android:textColor="@color/colorWhite"
            android:textColorHint="@color/colorWhite"
            android:ems="10"
            android:padding="@dimen/activity_vertical_margin"
            android:theme="@style/WhiteFocus" /&amp;gt;

        &amp;lt;EditText
            android:id="@+id/email"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:inputType="textEmailAddress"
            android:hint="@string/email"
            android:textColor="@color/colorWhite"
            android:textColorHint="@color/colorWhite"
            android:ems="10"
            android:padding="@dimen/activity_vertical_margin"
            android:theme="@style/WhiteFocus" /&amp;gt;

        &amp;lt;EditText
            android:id="@+id/password"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:inputType="textPassword"
            android:hint="@string/password"
            android:textColor="@color/colorWhite"
            android:textColorHint="@color/colorWhite"
            android:ems="10"
            android:padding="@dimen/activity_vertical_margin"
            android:theme="@style/WhiteFocus" /&amp;gt;

    &amp;lt;/LinearLayout&amp;gt;

    &amp;lt;LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"&amp;gt;

        &amp;lt;Button
            android:id="@+id/btn_register"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/register"
            android:background="@drawable/btn_background"
            android:textColor="@color/colorPrimary" /&amp;gt;

    &amp;lt;/LinearLayout&amp;gt;

&amp;lt;/RelativeLayout&amp;gt;
&lt;/pre&gt;
activity_main.xml
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:windowSoftInputMode="adjustResize"
    tools:context="com.wimso.androidloginandregistration.MainActivity"&amp;gt;

    &amp;lt;LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true"
        android:orientation="vertical"&amp;gt;

        &amp;lt;TextView
            android:id="@+id/greeting"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:textSize="48sp"
            android:textColor="@color/colorText" /&amp;gt;


        &amp;lt;TextView
            android:id="@+id/email"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:textColor="@color/colorText" /&amp;gt;

    &amp;lt;/LinearLayout&amp;gt;

    &amp;lt;LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"&amp;gt;

        &amp;lt;Button
            android:id="@+id/btn_logout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/logout"
            android:background="@drawable/btn_background_2"
            android:textColor="@color/colorWhite"/&amp;gt;

    &amp;lt;/LinearLayout&amp;gt;

&amp;lt;/RelativeLayout&amp;gt;

&lt;/pre&gt;
Buat package network→ config lalu buat kelas dengan nama &lt;b&gt;Config.java&lt;/b&gt;. Di kelas ini kita akan mendeklarasikan url dan endpoint pada API yang telah kita buat. Base url yang ditentukan dari IP localhost yang digunakan.
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;/**
 * Created by Wim on 11/4/16.
 */
public class Config {

    public static final String BASE_URL = "YOUR IP ADDRESS"; // Your Local IP Address or Localhost (http://10.0.2.2/)

    public static final String API_URL = BASE_URL + "/simple_api";

    public static final String API_LOGIN = API_URL + "/login.php";
    public static final String API_REGISTER = API_URL + "/register.php";

}
&lt;/pre&gt;
Masih di package yang sama, buat kelas dengan nama &lt;b&gt;RetrofitBuilder.java&lt;/b&gt;
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import com.wimso.androidloginandregistration.BuildConfig;

import java.util.concurrent.TimeUnit;
import android.content.Context;

import okhttp3.Cache;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * Created by Wim on 11/4/16.
 */
public class RetrofitBuilder {

    public static Retrofit builder(Context context) {
        OkHttpClient.Builder okhttpBuilder = new OkHttpClient().newBuilder();
        okhttpBuilder.connectTimeout(60, TimeUnit.SECONDS);
        okhttpBuilder.writeTimeout(60, TimeUnit.SECONDS);
        okhttpBuilder.readTimeout(60, TimeUnit.SECONDS);

        int cacheSize = 10 * 1024 * 1024;
        Cache cache = new Cache(context.getCacheDir(), cacheSize);
        okhttpBuilder.cache(cache);

        if (BuildConfig.DEBUG) {
            HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
            interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
            okhttpBuilder.addInterceptor(interceptor);
        }

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(Config.BASE_URL)
                .client(okhttpBuilder.build())
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        return retrofit;
    }
}

&lt;/pre&gt;
Dari package network, buat package interfaces kemudian tambahkan interface &lt;b&gt;LoginInterface.java&lt;/b&gt; dan &lt;b&gt;RegisterInterface.java&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
LoginInterface.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import com.wimso.androidloginandregistration.model.User;
import com.wimso.androidloginandregistration.network.config.Config;

import retrofit2.Call;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.POST;

/**
 * Created by Wim on 11/3/16.
 */
public interface LoginInterface {

    @FormUrlEncoded
    @POST(Config.API_LOGIN)
    Call&amp;lt;User&amp;gt; login(
            @Field("email") String email,
            @Field("password") String password);

}

&lt;/pre&gt;
RegisterInterface.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import com.wimso.androidloginandregistration.model.BaseResponse;
import com.wimso.androidloginandregistration.network.config.Config;

import retrofit2.Call;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.POST;

/**
 * Created by Wim on 11/4/16.
 */
public interface RegisterInterface {

    @FormUrlEncoded
    @POST(Config.API_REGISTER)
    Call&amp;lt;BaseResponse&amp;gt; register(
            @Field("firstname") String firstname,
            @Field("lastname") String lastname,
            @Field("email") String email,
            @Field("password") String password);

}

&lt;/pre&gt;
Kemudian di package network buat kelas &lt;b&gt;LoginService.java&lt;/b&gt; dan &lt;b&gt;RegisterService.java&lt;/b&gt; berikut :&lt;br /&gt;
&lt;br /&gt;
LoginService.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import android.content.Context;

import com.wimso.androidloginandregistration.network.config.RetrofitBuilder;
import com.wimso.androidloginandregistration.network.interfaces.LoginInterface;

import retrofit2.Callback;

/**
 * Created by Wim on 11/4/16.
 */
public class LoginService {

    private LoginInterface loginInterface;

    public LoginService(Context context) {
        loginInterface = RetrofitBuilder.builder(context)
                .create(LoginInterface.class);
    }

    public void doLogin(String email, String password, Callback callback) {
        loginInterface.login(email, password).enqueue(callback);
    }

}
&lt;/pre&gt;
RegisterService.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import android.content.Context;

import com.wimso.androidloginandregistration.network.config.RetrofitBuilder;
import com.wimso.androidloginandregistration.network.interfaces.RegisterInterface;

import retrofit2.Callback;

/**
 * Created by Wim on 11/4/16.
 */
public class RegisterService {

    private RegisterInterface registerInterface;

    public RegisterService(Context context) {
        registerInterface = RetrofitBuilder.builder(context)
                .create(RegisterInterface.class);
    }

    public void doRegister(String firstname, String lastname, String email, String password, Callback callback) {
        registerInterface.register(firstname, lastname, email, password).enqueue(callback);
    }

}
&lt;/pre&gt;
Kemudian buat package &lt;b&gt;model&lt;/b&gt; yang berisi kelas model datanya sesuai dengan response json yang akan di mapping dalam bentuk kelas pojos. &lt;br /&gt;
&lt;br /&gt;
Buat kelas dengan nama &lt;b&gt;BaseResponse.java
&lt;/b&gt;&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;/**
 * Created by Wim on 11/4/16.
 */
public class BaseResponse {

    private boolean error;
    private String message;

    public BaseResponse() {
    }

    public boolean isError() {
        return error;
    }

    public void setError(boolean error) {
        this.error = error;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

&lt;/pre&gt;
Buat kelas dengan nama &lt;b&gt;User.java
&lt;/b&gt;&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;/**
 * Created by Wim on 11/4/16.
 */
public class User extends BaseResponse {

    private UserData data;

    public User() {
    }

    public UserData getData() {
        return data;
    }

    public void setData(UserData data) {
        this.data = data;
    }
}

&lt;/pre&gt;
Buat kelas dengan nama &lt;b&gt;UserData.java&lt;/b&gt;
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;/**
 * Created by Wim on 11/4/16.
 */
public class UserData {

    private String firstname;
    private String lastname;
    private String email;

    public UserData() {
    }

    public String getFirstname() {
        return firstname;
    }

    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }

    public String getLastname() {
        return lastname;
    }

    public void setLastname(String lastname) {
        this.lastname = lastname;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}
&lt;/pre&gt;
Selanjutnya buat package &lt;b&gt;util&lt;/b&gt; kemudian buat kelas &lt;b&gt;PrefUtil.java&lt;/b&gt; untuk menyimpan data di SharedPreferences.
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;

import com.google.gson.Gson;
import com.wimso.androidloginandregistration.model.User;

/**
 * Created by Wim on 11/3/16.
 */
public class PrefUtil {

    public static final String USER_SESSION = "user_session";

    public static SharedPreferences getSharedPreference(Context context) {
        return PreferenceManager.getDefaultSharedPreferences(context);
    }

    public static void putUser(Context context, String key, User user) {
        Gson gson = new Gson();
        String json = gson.toJson(user);
        putString(context, key, json);
    }

    public static User getUser(Context context, String key) {
        Gson gson = new Gson();
        String json = getString(context, key);
        User user = gson.fromJson(json, User.class);
        return user;
    }

    public static void putString(Context context, String key, String value) {
        getSharedPreference(context).edit().putString(key, value).apply();
    }

    public static String getString(Context context, String key) {
        return getSharedPreference(context).getString(key, null);
    }

    public static void clear(Context context) {
        getSharedPreference(context).edit().clear().apply();
    }

}

&lt;/pre&gt;
Buat kelas activity dengan nama &lt;b&gt;LoginActivity.java&lt;/b&gt; untuk proses login user.
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.text.Html;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.text.style.ForegroundColorSpan;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.wimso.androidloginandregistration.model.User;
import com.wimso.androidloginandregistration.network.LoginService;
import com.wimso.androidloginandregistration.util.PrefUtil;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

/**
 * Created by Wim on 10/31/16.
 */
public class LoginActivity extends AppCompatActivity {

    private EditText emailText;
    private EditText passwordText;
    private Button btnLogin;
    private TextView registerCaption;

    private LoginService loginService;

    public static void start(Context context) {
        Intent intent = new Intent(context, LoginActivity.class);
        context.startActivity(intent);
    }

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

        if(isSessionLogin()) {
            MainActivity.start(this);
            LoginActivity.this.finish();
        }

        emailText = (EditText) findViewById(R.id.email);
        passwordText = (EditText) findViewById(R.id.password);
        btnLogin = (Button) findViewById(R.id.btn_login);
        registerCaption = (TextView) findViewById(R.id.register_caption);

        btnLogin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                loginAct();
            }
        });

        String caption = "Dont have an account? &amp;lt;b&amp;gt;Register&amp;lt;/b&amp;gt;";
        SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(Html.fromHtml(caption));
        spannableStringBuilder.setSpan(new ClickableSpan() {
            @Override
            public void onClick(View view) {
                RegisterActivity.start(LoginActivity.this);
            }
        }, caption.indexOf("Register") - 3, spannableStringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        spannableStringBuilder.setSpan(new ForegroundColorSpan(Color.WHITE), caption
                .indexOf("Register") - 3, spannableStringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

        registerCaption.setText(spannableStringBuilder);
        registerCaption.setMovementMethod(LinkMovementMethod.getInstance());

    }

    void loginAct() {
        String email = emailText.getText().toString();
        String password = passwordText.getText().toString();

        if(TextUtils.isEmpty(email)) {
            emailText.setError("Email cannot be empty!");
            return;
        }

        if(TextUtils.isEmpty(password)) {
            passwordText.setError("Password cannot be empty");
            return;
        }

        loginService = new LoginService(this);
        loginService.doLogin(email, password, new Callback() {
            @Override
            public void onResponse(Call call, Response response) {
                User user = (User) response.body();

                if(user != null) {
                    if(!user.isError()) {
                        PrefUtil.putUser(LoginActivity.this, PrefUtil.USER_SESSION, user);
                        MainActivity.start(LoginActivity.this);
                        LoginActivity.this.finish();
                    }

                    Toast.makeText(LoginActivity.this, user.getMessage(), Toast.LENGTH_SHORT).show();
                }
            }

            @Override
            public void onFailure(Call call, Throwable t) {
                Toast.makeText(LoginActivity.this, "An error occurred!", Toast.LENGTH_SHORT).show();
            }
        });
    }

    boolean isSessionLogin() {
        return PrefUtil.getUser(this, PrefUtil.USER_SESSION) != null;
    }
}

&lt;/pre&gt;
Buat kelas dengan nama &lt;b&gt;RegisterActivity.java&lt;/b&gt; untuk proses register user.
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import android.content.Context;
import android.content.Intent;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import com.wimso.androidloginandregistration.model.BaseResponse;
import com.wimso.androidloginandregistration.network.RegisterService;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class RegisterActivity extends AppCompatActivity {

    private Toolbar toolbar;

    private EditText firstnameText;
    private EditText lastnameText;
    private EditText emailText;
    private EditText passwordText;

    private Button btnRegister;

    private RegisterService registerService;

    public static void start(Context context) {
        Intent intent = new Intent(context, RegisterActivity.class);
        context.startActivity(intent);
    }

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

        toolbar = (Toolbar) findViewById(R.id.toolbar);

        firstnameText = (EditText) findViewById(R.id.firstname);
        lastnameText = (EditText) findViewById(R.id.lastname);
        emailText = (EditText) findViewById(R.id.email);
        passwordText = (EditText) findViewById(R.id.password);
        btnRegister = (Button) findViewById(R.id.btn_register);

        setSupportActionBar(toolbar);

        ActionBar actionBar = getSupportActionBar();
        if(actionBar != null) {
            actionBar.setDisplayHomeAsUpEnabled(true);
        }

        btnRegister.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                registerAct();
            }
        });
    }

    void registerAct() {
        String firstname = firstnameText.getText().toString();
        String lastname = lastnameText.getText().toString();
        String email = emailText.getText().toString();
        String password = passwordText.getText().toString();

        if(TextUtils.isEmpty(firstname)) {
            firstnameText.setError("Firstname cannot be empty !");
            return;
        }

        if(TextUtils.isEmpty(lastname)) {
            firstnameText.setError("Lastname cannot be empty !");
            return;
        }

        if(TextUtils.isEmpty(email)) {
            firstnameText.setError("Email cannot be empty !");
            return;
        }

        if(TextUtils.isEmpty(password)) {
            firstnameText.setError("Password cannot be empty !");
            return;
        }

        registerService = new RegisterService(this);
        registerService.doRegister(firstname, lastname, email, password, new Callback() {
            @Override
            public void onResponse(Call call, Response response) {
                BaseResponse baseResponse = (BaseResponse) response.body();

                if(baseResponse != null) {
                    if(!baseResponse.isError()) {
                        LoginActivity.start(RegisterActivity.this);
                        RegisterActivity.this.finish();
                    }

                    Toast.makeText(RegisterActivity.this, baseResponse.getMessage(), Toast.LENGTH_SHORT).show();
                }
            }

            @Override
            public void onFailure(Call call, Throwable t) {
                Toast.makeText(RegisterActivity.this, "An error occurred!", Toast.LENGTH_SHORT).show();
            }
        });

    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                onBackPressed();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

}
&lt;/pre&gt;
Buat kelas &lt;b&gt;MainActivity.java&lt;/b&gt; sebagai dashboard user.
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import android.content.Context;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.wimso.androidloginandregistration.model.User;
import com.wimso.androidloginandregistration.util.PrefUtil;

public class MainActivity extends AppCompatActivity {

    private TextView greeting;
    private TextView email;
    private Button btnLogout;

    public static void start(Context context) {
        Intent intent = new Intent(context, MainActivity.class);
        context.startActivity(intent);
    }

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

        greeting = (TextView) findViewById(R.id.greeting);
        email = (TextView) findViewById(R.id.email);
        btnLogout = (Button) findViewById(R.id.btn_logout);

        User user = PrefUtil.getUser(this, PrefUtil.USER_SESSION);

        greeting.setText(getResources().getString(R.string.greeting, user.getData().getFirstname()));
        email.setText(user.getData().getEmail());

        btnLogout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                logoutAct();

                LoginActivity.start(MainActivity.this);
                MainActivity.this.finish();
            }
        });

    }

    void logoutAct() {
        PrefUtil.clear(this);
    }
}

&lt;/pre&gt;
Terakhir adalah tambahkan permission internet di AndroidManifest.xml
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;uses-permission android:name="android.permission.INTERNET" /&amp;gt;
&lt;/pre&gt;
Build dan jalankan maka hasilnya sebagai berikut :
&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrGJ0KQh-j8HBDtJ0Ka3TZDIV6yK-02zPpXL_Dc9OOXxmp99VDX0NbvjpXhLM_GFk_Vg_eJ5EC5apLi0_YxkApeg4E76bDIlIopXmnhPTEQvOiK4jr2NLV8b46vmzAgwJ6HEgeye4o-wA/s1600/device-2016-11-10-145846.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrGJ0KQh-j8HBDtJ0Ka3TZDIV6yK-02zPpXL_Dc9OOXxmp99VDX0NbvjpXhLM_GFk_Vg_eJ5EC5apLi0_YxkApeg4E76bDIlIopXmnhPTEQvOiK4jr2NLV8b46vmzAgwJ6HEgeye4o-wA/s400/device-2016-11-10-145846.png" width="225" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjD8mkpEYhLCsPZe6zcPijHv3M3mvBSiNib8FgZoSRGi1FNOy9lUafHbbeFf4h5zF_eAabS_alOmyqsrFlDy_J0c5vorf31FEEar_sWY3dA7VzoZFfxv2dxeM46Ma0xX0j-NazFkXA-YHA/s1600/device-2016-11-10-145924.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjD8mkpEYhLCsPZe6zcPijHv3M3mvBSiNib8FgZoSRGi1FNOy9lUafHbbeFf4h5zF_eAabS_alOmyqsrFlDy_J0c5vorf31FEEar_sWY3dA7VzoZFfxv2dxeM46Ma0xX0j-NazFkXA-YHA/s400/device-2016-11-10-145924.png" width="225" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9mBTJvqV9yxJtuMehNRUb12EHIjkUWdplJSHLO4irGBmr5CYon9Ep4XsEZ-BA7d5u4ck32subRiumNQkRiT7ZiKGMdP0ENHRGoBem7FVJvC7Kx7_P0XeazwYbzKyq89I2SDQuHnWW42s/s1600/device-2016-11-10-145940.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9mBTJvqV9yxJtuMehNRUb12EHIjkUWdplJSHLO4irGBmr5CYon9Ep4XsEZ-BA7d5u4ck32subRiumNQkRiT7ZiKGMdP0ENHRGoBem7FVJvC7Kx7_P0XeazwYbzKyq89I2SDQuHnWW42s/s400/device-2016-11-10-145940.png" width="225" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Source code lengkap dapat dilihat di&amp;nbsp;&lt;a href="https://github.com/wimsonevel/AndroidLoginAndRegistration"&gt;https://github.com/wimsonevel/AndroidLoginAndRegistration&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Sekian tutorial dari saya kali ini.&lt;br /&gt;
Semoga bermanfaat.&lt;br /&gt;
&lt;br /&gt;
Happy Coding :)</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwj185x9HmhAn54EM2h_RwW08o_JogjnSVXYPpcbNbxeoGcFjqWzsD6wbAuK84pLPEzfDSdm57kUo01ajl3WKT_CzYbyUpBS-uCJ7hBRW1rZ-2Za5BkpQG9CyzszQ9jCJqaFk9CumCfdQ/s72-c/android-loginandregistration.png" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">105</thr:total></item><item><title>(Chord Tutorial) JKT48 - Candy</title><link>http://wimsonevel.blogspot.com/2016/11/chord-tutorial-jkt48-candy.html</link><category>Chord</category><category>Chord JKT48</category><author>noreply@blogger.com (Wim Sonevel)</author><pubDate>Wed, 9 Nov 2016 12:59:00 +0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-6966757688576433754.post-8373377117391979907</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbITtYUKfZcm3FTHKhNHqRMIdP4tCYftr5aIt0IxZ1w-o6rSvJAvmdDoxLI3MdUktMuRMaoPu5jPfqx50lktlEeMWqjdIMDm8IEi7H-RlKdUoINA6byc8X2M84rJLYuPYF2gh8I7DvqjI/s1600/michelle-gracia-anin_23310404072_o.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="265" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbITtYUKfZcm3FTHKhNHqRMIdP4tCYftr5aIt0IxZ1w-o6rSvJAvmdDoxLI3MdUktMuRMaoPu5jPfqx50lktlEeMWqjdIMDm8IEi7H-RlKdUoINA6byc8X2M84rJLYuPYF2gh8I7DvqjI/s400/michelle-gracia-anin_23310404072_o.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Satu lagi lagu ceria yang dibawakan oleh JKT48 yang berjudul "Candy". Lagu adalah salah satu lagu yang terdapat di setlist terbarunya JKT48 Tim J. Sebenarnya lagu ini pertama kali dibawakan oleh member generasi ke-3 JKT48 yaitu Michelle, Gracia dan Anin.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="text-align: center;"&gt;
&lt;iframe allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/66kD-f4h2sA" width="560"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Jujur TS suka banget sama lagu ini .. :'v&lt;br /&gt;
Entah kenapa lagu ini bikin gregetan :3&lt;br /&gt;
Liriknya juga asik, TS bisa bilang ini adalah lagu paling ceria diantara semua lagu JKT48. &amp;nbsp;:3&lt;br /&gt;
&lt;br /&gt;
Daripada versi setlistnya, TS lebih suka ketika lagu ini dibawakan oleh member generasi ke-3 tersebut.&lt;br /&gt;
&lt;br /&gt;
Oke langsung saja TS akan membagikan chord tutorialnya, cekidot.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Intro : D E D E&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
D&lt;br /&gt;
Candy sebuah ya&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;E&lt;br /&gt;
masukkan ke mulut&lt;br /&gt;
&amp;nbsp; &amp;nbsp;C#m &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;F#m&lt;br /&gt;
kemudian diputar-putar di atas lidah&lt;br /&gt;
&amp;nbsp; &amp;nbsp;D &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;C#m &amp;nbsp; &amp;nbsp; &amp;nbsp; Bm E&lt;br /&gt;
rasa manis dan sedikit asam&lt;br /&gt;
&lt;br /&gt;
Ceria…&lt;br /&gt;
&lt;br /&gt;
D E C#m F#m 2x&lt;br /&gt;
Lalalalalalala… Lalalalalalala...&lt;br /&gt;
Everybody get! Everybody eat!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
D &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; E&lt;br /&gt;
Motor 50 CC&lt;br /&gt;
&amp;nbsp; &amp;nbsp; C#m &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;F#m&lt;br /&gt;
ku naiki dan jalan-jalan&lt;br /&gt;
D &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; E&lt;br /&gt;
akhir siang di hari Sabtu&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;C#m &amp;nbsp; &amp;nbsp; &amp;nbsp; F#m&lt;br /&gt;
sang mentari ulala&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;D &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Dm&lt;br /&gt;
Mendengar music di iPod&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; C#m &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;F#m&lt;br /&gt;
lagu penyanyi favoritku&lt;br /&gt;
D &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;E &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Em&lt;br /&gt;
karena bisa membuatku terlupa&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; A7&lt;br /&gt;
semua hal yang tak menyenangkan&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Reff :&lt;br /&gt;
&lt;br /&gt;
D&lt;br /&gt;
Candy sebuah ya !&lt;br /&gt;
E&lt;br /&gt;
ada dalam pipi&lt;br /&gt;
C#m &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; F#m&lt;br /&gt;
bagaikan mantra untuk menjadi bahagia&lt;br /&gt;
D &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; E&lt;br /&gt;
Everybody get! Everybody eat!&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Em &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;A7&lt;br /&gt;
mau pergi ke mana?&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; D &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; E&lt;br /&gt;
anak perempuan selalu optimis&lt;br /&gt;
C#m &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; C# &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; F#m &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; G&lt;br /&gt;
dalam hidup semua masalah pasti kan berlalu&lt;br /&gt;
D &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;C#m &amp;nbsp; &amp;nbsp; &amp;nbsp;Bm E&lt;br /&gt;
sebuah permen selalu terasa dalam hati&lt;br /&gt;
&lt;br /&gt;
D &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;E&lt;br /&gt;
Lari di tengah pertokoan&lt;br /&gt;
&amp;nbsp; &amp;nbsp; C#m &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; F#m&lt;br /&gt;
melirik ke pasar loak&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; D &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; E&lt;br /&gt;
dan melambaikan tangan ke teman&lt;br /&gt;
C#m &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;F#m&lt;br /&gt;
lalu beli majalah&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;D &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Dm&lt;br /&gt;
Dan untuk menenangkan anak kecil&lt;br /&gt;
C#m &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; F#m&lt;br /&gt;
yang suka menangis&lt;br /&gt;
D &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;E &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Em&lt;br /&gt;
jikalau ada hadiah pasti akan&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;A7&lt;br /&gt;
jadi lebih semangat&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Reff :&lt;br /&gt;
&lt;br /&gt;
D&lt;br /&gt;
Candy sebuah ya !&lt;br /&gt;
E&lt;br /&gt;
jika diberikan&lt;br /&gt;
C#m &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;F#m&lt;br /&gt;
keluhan dan gerutu akan jadi berhenti&lt;br /&gt;
D &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; E&lt;br /&gt;
Everybody get! Everybody eat!&lt;br /&gt;
Em &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; A7&lt;br /&gt;
harus berbuat apa?&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; D &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;E&lt;br /&gt;
anak perempuan itu sangat labil&lt;br /&gt;
C#m &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;C# &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; F#m &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; G&lt;br /&gt;
selalu saja meminta sesuatu hal yang lebih&lt;br /&gt;
D &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; C#m &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Bm E&lt;br /&gt;
menyenangkan daripada sekarang mencari permen&lt;br /&gt;
&lt;br /&gt;
Bridge&lt;br /&gt;
D &amp;nbsp; &amp;nbsp; &amp;nbsp;C# &amp;nbsp; &amp;nbsp; &amp;nbsp; F#m &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Em &amp;nbsp; F# &amp;nbsp;Bm&lt;br /&gt;
Pada saat air mata mengalir dan jatuh&lt;br /&gt;
C#m &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;D &amp;nbsp; &amp;nbsp; E &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; D&lt;br /&gt;
dari dalam kantong ya jurus itu&lt;br /&gt;
E&lt;br /&gt;
Fight!&lt;br /&gt;
Everybody! Fight!&lt;br /&gt;
&lt;br /&gt;
C#m&lt;br /&gt;
Everybody! Fight!&lt;br /&gt;
&lt;br /&gt;
F#m&lt;br /&gt;
F Em Dm&lt;br /&gt;
Haa…. ~ Haa…. ~&lt;br /&gt;
E&lt;br /&gt;
Huu…. ~&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Reff :&lt;br /&gt;
&lt;br /&gt;
D&lt;br /&gt;
Candy sebuah ya !&lt;br /&gt;
E&lt;br /&gt;
ada dalam pipi&lt;br /&gt;
C#m &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; F#m&lt;br /&gt;
bagaikan mantra untuk menjadi bahagia&lt;br /&gt;
D &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; E&lt;br /&gt;
Everybody get! Everybody eat!&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Em &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;A7&lt;br /&gt;
mau pergi ke mana?&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; D &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; E&lt;br /&gt;
anak perempuan selalu optimis&lt;br /&gt;
C#m &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; C# &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; F#m &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; G&lt;br /&gt;
dalam hidup semua masalah pasti kan berlalu&lt;br /&gt;
D &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;C#m &amp;nbsp; &amp;nbsp; &amp;nbsp;Bm E&lt;br /&gt;
sebuah permen selalu terasa dalam hati&lt;br /&gt;
&lt;br /&gt;
D E C#m F#m&lt;br /&gt;
Lalalalalalala… Lalalalalalala...&lt;br /&gt;
D E Em A7&lt;br /&gt;
Everybody get! Everybody eat!&lt;br /&gt;
D E C#m C# F#m G&lt;br /&gt;
Lalalalalalala… Lalalalalalala...&lt;br /&gt;
D C#m Bm E&lt;br /&gt;
Everybody get! Everybody eat!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Outro: D&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;b&gt;Bonus :&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibAYHwmOjtcG19jvK8WIKtOTO6SwDaQGE9D1pNpHqooOg52m-c6YkXIDq3ERhaBRkrAK6Bc3JAVgfjgzs_3O7LPh1r1r0QkO1f7xPyNRqutkDhA8gZsBpu_tNTES4CUWrcOglGyJ78k_c/s1600/15413853404_9a45ff5387_b.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibAYHwmOjtcG19jvK8WIKtOTO6SwDaQGE9D1pNpHqooOg52m-c6YkXIDq3ERhaBRkrAK6Bc3JAVgfjgzs_3O7LPh1r1r0QkO1f7xPyNRqutkDhA8gZsBpu_tNTES4CUWrcOglGyJ78k_c/s400/15413853404_9a45ff5387_b.jpg" width="266" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;&lt;/div&gt;
</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbITtYUKfZcm3FTHKhNHqRMIdP4tCYftr5aIt0IxZ1w-o6rSvJAvmdDoxLI3MdUktMuRMaoPu5jPfqx50lktlEeMWqjdIMDm8IEi7H-RlKdUoINA6byc8X2M84rJLYuPYF2gh8I7DvqjI/s72-c/michelle-gracia-anin_23310404072_o.jpg" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>(Chord Tutorial) JKT48 – Mae Shika Mukanee (Hanya Lihat Ke Depan)</title><link>http://wimsonevel.blogspot.com/2016/10/chord-tutorial-jkt48-mae-shika-mukanee.html</link><category>Chord</category><category>Chord JKT48</category><author>noreply@blogger.com (Wim Sonevel)</author><pubDate>Tue, 18 Oct 2016 13:46:00 +0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-6966757688576433754.post-8080461078705942937</guid><description>Single yang berjudul &lt;b&gt;Hanya Lihat Ke Depan (Mae Shika Mukanee) &lt;/b&gt;ini merupakan single ke-13 dari JKT48. &amp;nbsp;Single ini menjadi single sousenkyo hasil voting oleh para fans JKT48. Member-member yang masuk senbatsu diantaranya Jessica Veranda, Ghaida Farisya, Haruka Nakagawa, Cindy Yuvia, Melody Nurramdhani Laksani, Shania Junianatha, Priscillia Sari Dewi, Nabilah Ratna Ayu Azalia, Rina Chikano, Devi Kinal Putri, Shania Gracia, Michelle Christo Kusnadi, Gabriela Margareth, Dena Siti Rohyati, Dwi Putri Bonita, Thalia Ivanka. Oshi TS Yupi *gak nanyak&lt;br /&gt;
&lt;br /&gt;
&lt;iframe allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/1eEngMCVyUE" width="560"&gt;&lt;/iframe&gt;

&lt;br /&gt;
Kali ini saya mau share chord dari lagu ini. Lagunya asiik dan liriknya memotivasi. So Cekidot.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pre-Intro :&lt;br /&gt;
C G F&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;C &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; G &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;F &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;C&lt;br /&gt;
hanya lihat ke depan karena jika menoleh&lt;br /&gt;
&amp;nbsp; F &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Am &amp;nbsp; &amp;nbsp; &amp;nbsp; Dm G&lt;br /&gt;
air mata ini akan terlihat&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; C &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; G &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;F &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;G&lt;br /&gt;
memandang jauh ke depan dan membulatkan tekad&lt;br /&gt;
&amp;nbsp; F &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Am &amp;nbsp;G&lt;br /&gt;
ayo melangkah ke sana&lt;br /&gt;
&lt;br /&gt;
Intro :&lt;br /&gt;
C G F G&lt;br /&gt;
C G F G C&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; C &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; G &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Dm &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Am&lt;br /&gt;
bertemu denganmu dan selalu bersama&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;C &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; G &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; F &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; G &amp;nbsp; &amp;nbsp; C&lt;br /&gt;
masa remaja kita yang penuh kenakalan&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;C &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; G &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Dm &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Am&lt;br /&gt;
kita tahu bahwa hal yang teramat penting&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; C &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;G &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;F &amp;nbsp; &amp;nbsp; G &amp;nbsp; &amp;nbsp; &amp;nbsp;C&lt;br /&gt;
tuk kehidupan ini berada di masa depan&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Am &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; F &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; G &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;C&lt;br /&gt;
walaupun sekarang menyenangkan&lt;br /&gt;
&amp;nbsp; &amp;nbsp; Am &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;F &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; G &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; C&lt;br /&gt;
tetapi tak akan berlanjut selamanya&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; G&lt;br /&gt;
jangan terus terbuai&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; C &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;G &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; F &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;C&lt;br /&gt;
hanya lihat ke depan tuk terakhir kalinya&lt;br /&gt;
F &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Am &amp;nbsp; &amp;nbsp; Dm &amp;nbsp; &amp;nbsp; G&lt;br /&gt;
biarkan ku tampil dengan keren&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;C &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;G &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; F &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; C&lt;br /&gt;
walau aku masih takut pada tempat yang baru&lt;br /&gt;
&amp;nbsp; F &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;C &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;G&lt;br /&gt;
tidak ada kata mundur&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;F &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;C &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; F &amp;nbsp; &amp;nbsp; C&lt;br /&gt;
jika berpaling ke jalan di belakang&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;F &amp;nbsp; &amp;nbsp; &amp;nbsp; C &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Dm G&lt;br /&gt;
hanya ada angin yang bertiup&lt;br /&gt;
C G Am F&lt;br /&gt;
woo wooo woo wooo&lt;br /&gt;
C G F G C&lt;br /&gt;
woo wooo yess woo woo woo wooo&lt;br /&gt;
&lt;br /&gt;
C G F G&lt;br /&gt;
C G F G C&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;C &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;G &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Dm &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Am&lt;br /&gt;
waktu ku jatuh cinta kemudian patah hati&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; C &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;G &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; F &amp;nbsp; &amp;nbsp; &amp;nbsp; G &amp;nbsp; &amp;nbsp;C&lt;br /&gt;
lalu seperti anak kecil berdiri di ayunan&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;C &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;G &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Dm &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Am&lt;br /&gt;
kata-kata yang kotor semua ku teriakkan&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp;C &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; G &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;F &amp;nbsp; &amp;nbsp; G &amp;nbsp; &amp;nbsp;C&lt;br /&gt;
di saat itu pun kamu tetap menemani aku&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Am F &amp;nbsp; &amp;nbsp; &amp;nbsp; G &amp;nbsp; C&lt;br /&gt;
walau seberat apapun&lt;br /&gt;
&amp;nbsp; &amp;nbsp; Am &amp;nbsp; &amp;nbsp; &amp;nbsp; F &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; G &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;C&lt;br /&gt;
kesedihan tak berlanjut selamanya&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;G&lt;br /&gt;
ayo hadapilah&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;C &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;G &amp;nbsp; &amp;nbsp; &amp;nbsp;F &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;C&lt;br /&gt;
hanya lihat ke depan saatnya berpisah&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp;F &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Am Dm G&lt;br /&gt;
percayalah pada hari esok&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;C &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; G &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; F &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;C&lt;br /&gt;
walaupun tak ada dirimu, walaupun tak ada aku&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;F &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; C &amp;nbsp; &amp;nbsp; G&lt;br /&gt;
tetap bisa hidup sendiri&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; F &amp;nbsp; &amp;nbsp; &amp;nbsp;C &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;F &amp;nbsp; &amp;nbsp; &amp;nbsp;C&lt;br /&gt;
walau berjalan di jalur berbeda&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; F &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; C &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Dm G&lt;br /&gt;
langit yang luas menghubungkan kita&lt;br /&gt;
C G Am F&lt;br /&gt;
woo wooo woo wooo&lt;br /&gt;
C G F G C&lt;br /&gt;
woo wooo yess woo woo woo wooo&lt;br /&gt;
&lt;br /&gt;
Bridge :&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; C &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; G&lt;br /&gt;
saatnya tuk berangkat&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;F &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;C&lt;br /&gt;
ayo buanglah semua kenangan&lt;br /&gt;
&lt;br /&gt;
Interlude :&lt;br /&gt;
C G F G C&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Am &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;G &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; F &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;C&lt;br /&gt;
hanya lihat ke depan tuk terakhir kalinya&lt;br /&gt;
F &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Em &amp;nbsp; &amp;nbsp; Dm &amp;nbsp; &amp;nbsp; G&lt;br /&gt;
biarkan ku tampil dengan keren&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;C &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;G &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; F &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; C&lt;br /&gt;
walau aku masih takut pada tempat yang baru&lt;br /&gt;
&amp;nbsp; F &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;C &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;G&lt;br /&gt;
tidak ada kata mundur&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;F &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;C &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; F &amp;nbsp; &amp;nbsp; C&lt;br /&gt;
jika berpaling ke jalan di belakang&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;F &amp;nbsp; &amp;nbsp; &amp;nbsp; C &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Dm G&lt;br /&gt;
hanya ada angin yang bertiup&lt;br /&gt;
&lt;br /&gt;
C G Am F (4x)&lt;br /&gt;
woo ooo woo ooo woo ooo wooo ooo&lt;br /&gt;
wooo ooo woo ooo yesss&lt;br /&gt;
woo woo woo wooo&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Outro :&lt;br /&gt;
&lt;br /&gt;
C G F G&lt;br /&gt;
C G F G C</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://img.youtube.com/vi/1eEngMCVyUE/default.jpg" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>(Tutorial Android) Lambda Expression in Android using Retrolambda</title><link>http://wimsonevel.blogspot.com/2016/10/tutorial-android-lambda-expression-in.html</link><category>Android</category><author>noreply@blogger.com (Wim Sonevel)</author><pubDate>Mon, 3 Oct 2016 16:20:00 +0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-6966757688576433754.post-2412791382178181516</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiosKddaZOtW576KKGLvCakankVTQcWHjLlgT4JEdsjoDhdz_mqcZQbBWvtU44szXyVTn5qv8G078XQlb0PrdGe24djoavWzWn58DvuDqMfKE6oIhG0C-ipZsXKb7MKEfkjIbciel1KUBo/s1600/android-retrolambda.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiosKddaZOtW576KKGLvCakankVTQcWHjLlgT4JEdsjoDhdz_mqcZQbBWvtU44szXyVTn5qv8G078XQlb0PrdGe24djoavWzWn58DvuDqMfKE6oIhG0C-ipZsXKb7MKEfkjIbciel1KUBo/s640/android-retrolambda.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;b&gt;Lambda Expression &lt;/b&gt;adalah salah satu fitur penting yang ada di &lt;b&gt;Java 8&lt;/b&gt;. Lambda Expression membuat fungsionalitas menjadi data agar dapat dipassing ke dalam suatu method sebagai parameter.&lt;br /&gt;
&lt;br /&gt;
Lambda Expression memiliki sintaks seperti berikut :
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;parameter → expression body
&lt;/pre&gt;
&lt;br /&gt;
Selengkapnya mengenai Lambda Expression di Java bisa dibaca-baca di sini&amp;nbsp;&lt;a href="https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html"&gt;https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html&lt;/a&gt;
&lt;br /&gt;
*bilang aja TS susah jelasin :v
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Retrolambda&lt;/b&gt; adalah library yang memungkinkan kita dapat menggunakan lambda expression di Java 6, 7 dan  Android.&lt;br /&gt;
&lt;br /&gt;
Seperti apa penggunaan Retrolambda ini? Mari simak tutorial berikut.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Configuration&lt;/b&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;br /&gt;
- Install &lt;a href="http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html"&gt;JDK 8 &lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
- Tambahkan dependencies yang diperlukan di gradle.&lt;br /&gt;
Top-level
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;buildscript {
    repositories {
        jcenter()
        mavenCentral()
    }
    dependencies {
        ....
        classpath 'me.tatarka:gradle-retrolambda:3.3.0'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}
&lt;/pre&gt;
Module-level

&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;apply plugin: 'me.tatarka.retrolambda'

android {
    ...
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}
repositories {
    mavenCentral()
}
retrolambda {
    jvmArgs '-noverify'
}
&lt;/pre&gt;
&lt;br /&gt;
Contoh penggunaan Retrolambda misalkan pada event listener ketika button di click.&lt;br /&gt;
&lt;br /&gt;
- Tanpa Lambda Expression
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        
    }
});
&lt;/pre&gt;
- Dengan Lambda Expression
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt; 
button.setOnClickListener(view -&amp;gt; {
    textView.setText(getHello().hello());
});
&lt;/pre&gt;
Bisa kita lihat perbandingan kedua implementasi di atas bahwa dengan Lambda Expression menjadi lebih singkat.&lt;br /&gt;
&lt;br /&gt;
Selain itu kita juga bisa membuat sebuah interface yang mendefinisikan suatu fungsi. Misalnya buat fungsi untuk mencetak “Hello”.
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;public interface HelloFunction {
    String hello();
}
&lt;/pre&gt;
Memanggil method dari interface HelloFunction dengan Lambda Expression.
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;public HelloFunction getHello() {
    return ()  -&amp;gt; getString(R.string.hello);
}
&lt;/pre&gt;
&lt;br /&gt;
Selanjutnya implementasikan fungsi hello() yang sudah kita buat di MainActivity.
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package com.wimso.androidretrolambda;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

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

        TextView textView = (TextView) findViewById(R.id.textView);
        Button button = (Button) findViewById(R.id.button);

        button.setOnClickListener(view -&amp;gt; {
            textView.setText(getHello().hello());
        });
    }

    public HelloFunction getHello() {
        return () -&amp;gt; getString(R.string.hello);
    }
}

&lt;/pre&gt;
&lt;br /&gt;
Build dan jalankan maka hasilnya sebagai berikut :&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZyG6tpfDINugejJGVQVG5elEpI9YLWcTFSz6-XKCtP-2Mv84EY0eqD_FffydTZn95BHNH5VUH_ewtEXdcvLbUwaqhYvyhsgiR_B88A4uJRmO87hl_XvQ1BbCGzCb73mazR-9ovGWWb5s/s1600/device-2016-10-03-155505.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZyG6tpfDINugejJGVQVG5elEpI9YLWcTFSz6-XKCtP-2Mv84EY0eqD_FffydTZn95BHNH5VUH_ewtEXdcvLbUwaqhYvyhsgiR_B88A4uJRmO87hl_XvQ1BbCGzCb73mazR-9ovGWWb5s/s400/device-2016-10-03-155505.png" width="225" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Source code dapat dilihat di&amp;nbsp;&lt;a href="https://github.com/wimsonevel/Android-Retrolambda"&gt;https://github.com/wimsonevel/Android-Retrolambda&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Sekian tutorial singkat kali ini.&lt;br /&gt;
Semoga Bermanfat.
</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiosKddaZOtW576KKGLvCakankVTQcWHjLlgT4JEdsjoDhdz_mqcZQbBWvtU44szXyVTn5qv8G078XQlb0PrdGe24djoavWzWn58DvuDqMfKE6oIhG0C-ipZsXKb7MKEfkjIbciel1KUBo/s72-c/android-retrolambda.png" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>(Tutorial Android) Simplify Code with AndroidAnnotations</title><link>http://wimsonevel.blogspot.com/2016/09/tutorial-android-simplify-code-with.html</link><category>Android</category><author>noreply@blogger.com (Wim Sonevel)</author><pubDate>Wed, 21 Sep 2016 21:34:00 +0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-6966757688576433754.post-362023785290623324</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFL1-cvfmVu8kOC9YIOAoQqKjBYcRzOFmxIzJlU219Bly0UGNPZhteQCv6pifUPZ2F3gGcwEluBvCH0TcjUGmLmkkvt3KEp1Mz4Kb1WnRZPS7U0rRhOjX6bAXLf7m-FMBjnFJ7T4J85g8/s1600/android-annotations.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFL1-cvfmVu8kOC9YIOAoQqKjBYcRzOFmxIzJlU219Bly0UGNPZhteQCv6pifUPZ2F3gGcwEluBvCH0TcjUGmLmkkvt3KEp1Mz4Kb1WnRZPS7U0rRhOjX6bAXLf7m-FMBjnFJ7T4J85g8/s640/android-annotations.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;b&gt;&lt;a href="http://androidannotations.org/"&gt;AndroidAnnotations&lt;/a&gt;&lt;/b&gt; adalah sebuah framework open source yang diklaim mampu mempercepat pengembangan aplikasi Android. Selain itu juga menulis code menjadi lebih simpel dan ringkas (&lt;i&gt;less&lt;/i&gt;&lt;b&gt; &lt;/b&gt;&lt;i&gt;code&lt;/i&gt;) dan mudah untuk di-&lt;i&gt;maintenance&lt;/i&gt;. &lt;b&gt;AndroidAnnotations&lt;/b&gt; ini menggunakan annotations yang berfungsi menggantikan boilerplate code yang umum pada project Android. &lt;br /&gt;
&lt;br /&gt;
Lalu, apa itu &lt;b&gt;Annotation&lt;/b&gt;?
&lt;b&gt;Annotation&lt;/b&gt; adalah sebuah meta tag yang memberikan informasi tentang code program tetapi tidak berpenngaruh secara langsung pada code dan bukan bagian dari code program itu sendiri. &lt;br /&gt;
&lt;br /&gt;
Beberapa fitur yang dimiliki oleh AndroidAnnotations :&lt;br /&gt;
&lt;br /&gt;
- &lt;b&gt;Dependency Injection&lt;/b&gt; : kita dapat menginjeksi pada kelas yang membutuhkan seperti inject views, extras, system services, resource dan lain-lain.&lt;br /&gt;
- &lt;b&gt;Simplified threading model&lt;/b&gt; : annotation dapat digunakan untuk menjalankan method di UI thread maupun background thread.&lt;br /&gt;
- &lt;b&gt;Event binding&lt;/b&gt; : Event handling menggunakan annotation.&lt;br /&gt;
- &lt;b&gt;REST Client&lt;/b&gt; : Request ke REST cukup dengan membuat client interface.&lt;br /&gt;
- AndroidAnnotations akan mengenerate subsclasses pada saat compile.&lt;br /&gt;
- Size kurang dari &lt;b&gt;150kb&lt;/b&gt; !
&lt;br /&gt;
&lt;br /&gt;
Daftar annotation yang tersedia bisa dilihat di &lt;a href="https://github.com/excilys/androidannotations/wiki/AvailableAnnotations%C2%A0"&gt;https://github.com/excilys/androidannotations/wiki/AvailableAnnotations&amp;nbsp;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Pada tutorial kali ini saya akan coba berbagi informasi sedikit tentang AndroidAnnotations. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style="font-size: large;"&gt;Configuration
&lt;/span&gt;&lt;/b&gt;
&lt;br /&gt;
&lt;br /&gt;
Langkah pertama adalah melakukan konfigurasi AndroidAnnotations dan library-library yang kita perlukan di gradle.&lt;br /&gt;
&lt;br /&gt;
Top-level
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;dependencies {
    ...
    classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
&lt;/pre&gt;
Module-level
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;apply plugin: 'com.android.application'
apply plugin: 'android-apt'
def AAVersion = '4.1.0'
def AppVersion = '23.3.0'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.3"

    defaultConfig {
        applicationId "com.wimso.android_aa"
        minSdkVersion 15
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

repositories {
    mavenCentral()
    mavenLocal()
    maven {
        url 'https://repo.spring.io/libs-milestone'
    }
}
android {
    packagingOptions {
        exclude 'META-INF/notice.txt'
        exclude 'META-INF/license.txt'
    }
}

apt {
    arguments {
        androidManifestFile variant.outputs[0]?.processResources?.manifestFile
        // if you have multiple outputs (when using splits), you may want to have other index than 0
        // you should set your package name here if you are using different application IDs
        // resourcePackageName "your.package.name"
        // You can set optional annotation processing options here, like these commented options:
        // logLevel 'INFO'
        // logFile '/var/log/aa.log'
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile "com.android.support:appcompat-v7:$AppVersion"
    compile "com.android.support:design:$AppVersion"
    compile "com.android.support:cardview-v7:$AppVersion"

    apt "org.androidannotations:androidannotations:$AAVersion"
    compile "org.androidannotations:androidannotations-api:$AAVersion"

    apt "org.androidannotations:rest-spring:$AAVersion"
    compile "org.androidannotations:rest-spring-api:$AAVersion"

    compile 'org.springframework.android:spring-android-rest-template:2.0.0.M3'
    compile 'com.google.code.gson:gson:2.7'
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Creating Layout&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Disini tidak ada yang berbeda ketika membuat layout, sama seperti membuat layout di Android pada umumnya. Buat sebuah layout dengan nama &lt;b&gt;activity_main.xml&lt;/b&gt;. Tambahkan beberapa komponen seperti TextView, EditText dan Button.&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.wimso.android_aa.MainActivity"&amp;gt;

    &amp;lt;LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"&amp;gt;

        &amp;lt;EditText
            android:id="@+id/post_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:hint="Post ID undefined1 - 100)"/&amp;gt;

        &amp;lt;Button
            android:id="@+id/btn_post"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="SHOW POST"/&amp;gt;

    &amp;lt;/LinearLayout&amp;gt;

    &amp;lt;LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/activity_vertical_margin"
        android:orientation="vertical"&amp;gt;

        &amp;lt;TextView
            android:id="@+id/post_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceMedium"/&amp;gt;

        &amp;lt;TextView
            android:id="@+id/post_body"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="5dp"
            android:textAppearance="?android:attr/textAppearanceSmall"/&amp;gt;

    &amp;lt;/LinearLayout&amp;gt;


&amp;lt;/LinearLayout&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Enhanced Activity and Injecting Views&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Mendefinisikan layout pada Activity biasanya dengan cara memanggil method &lt;b&gt;setContentView() &lt;/b&gt;yang ada di dalam method &lt;b&gt;onCreate()&lt;/b&gt;. Nah, kalau di AndroidAnnotations cara mendefinisikannya dapat diringkas dengan menggunakan annotation &lt;b&gt;@EActivity&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;@EActivity&lt;/b&gt; : annotation yang menunjukkan bahwa suatu activity akan di &lt;i&gt;enhanced&lt;/i&gt; oleh AndroidAnnotations.&lt;br /&gt;
&lt;br /&gt;
Memanggil komponen tidak menggunakan &lt;b&gt;findViewById&lt;/b&gt; seperti pada umumnya. Tapi dengan menginjeksi view menggunakan annotation &lt;b&gt;@ViewById&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;@ViewById&lt;/b&gt; : annotation yang menunjukkan injeksi dari component view pada layout.&lt;br /&gt;
&amp;nbsp;*Perlu diperhatikan bahwa ketika field disisipi annotation &lt;b&gt;@ViewById&lt;/b&gt; ini field masih kosong dan field tidak boleh private.&lt;br /&gt;
&lt;br /&gt;
Ketika &lt;b&gt;onCreate()&lt;/b&gt; dipanggil, maka field &lt;b&gt;@ViewById&lt;/b&gt; sebenarnya masih kosong, jadi kita dapat mengeset valuenya pada method yang ditambahin annotation &lt;b&gt;@AfterViews&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;@AfterViews&lt;/b&gt; : annotation yang menunjukkan bahwa method harus dipanggil setelah views binding. *yak, kurang lebih begitu :v&lt;br /&gt;
&lt;br /&gt;
Tapi intinya, kita dapat mengeset value sebuah field dari &lt;b&gt;@ViewById&lt;/b&gt; dengan cara memanggil annotation &lt;b&gt;@AfterViews&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
Berikut contohnya pada MainActivity :
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;@EActivity(R.layout.activity_main)
public class MainActivity extends AppCompatActivity {

    @ViewById(R.id.post_text) EditText postText;
    @ViewById(R.id.post_title) TextView postTitle;
    @ViewById(R.id.post_body) TextView postBody;
    @RestService ApiService apiService;

    private ProgressDialog progressDialog;

    @AfterViews
    public void bindViews() {
        // Default Text
        postText.setText("1");
        progressDialog = new ProgressDialog(this);
        progressDialog.setMessage("Loading...");
        progressDialog.setCancelable(true);
    }
    
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style="font-size: large;"&gt;Event Binding&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
AndroidAnnotations menyediakan annotation untuk menhandel event listener. Contohnya untuk menhandel event click menggunakan annotation &lt;b&gt;@Click&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;@Click&lt;/b&gt; : annotation yang menunjukkan method di activity bisa memanggil event click pada view.&lt;br /&gt;
&lt;br /&gt;
Contohnya penggunaannya :
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;@Click(R.id.btn_post)
void getPostClicked() {

   // do something
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;REST Client&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Untuk melakukan request ke &lt;b&gt;REST API&lt;/b&gt; yakni dengan membuat client interface. REST API dapat bekerja dengan annotation &lt;b&gt;@Rest&lt;/b&gt;.
Pada kasus ini kita menggunakan REST Client &lt;a href="http://projects.spring.io/spring-android/"&gt;&lt;b&gt;Spring Android&lt;/b&gt;&lt;/a&gt; &amp;nbsp;yang terintegrasi dengan AndroidAnnotations.&lt;br /&gt;
&lt;br /&gt;
Contohnya :
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;@Rest(rootUrl = "https://jsonplaceholder.typicode.com", converters = { GsonHttpMessageConverter.class })
public interface ApiService {

    @Get("/posts/{id}")
    Post getPost(@Path String id);

}
&lt;/pre&gt;
&lt;b&gt;rootUrl&lt;/b&gt; merupakan base url nya, sedangkan &lt;b&gt;converters&lt;/b&gt; wajib di definisikan. Converters ini berfungsi menconvert hasil respon yang di dapat yang kemudian dapat di mapping. Pada contoh di atas kita menggunakan converter dari &lt;b&gt;GSON&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
Request ke REST API dapat berupa &lt;b&gt;GET&lt;/b&gt; atau &lt;b&gt;POST&lt;/b&gt;, gunakan &lt;b&gt;@Get&lt;/b&gt; atau &lt;b&gt;@Post&lt;/b&gt; untuk mendefinisikan sebuah request &lt;b&gt;GET&lt;/b&gt; atau &lt;b&gt;POST&lt;/b&gt;.
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style="font-size: large;"&gt;Background Task
&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Annotation&lt;b&gt; @Background &lt;/b&gt;dan &lt;b&gt;@UiThread&lt;/b&gt; dapat digunakan untuk menjalankan Background Task. Annotation &lt;b&gt;@Background&lt;/b&gt; bekerja sama halnya seperti &lt;b&gt;AsyncTask&lt;/b&gt;. Sedangkan &lt;b&gt;@UiThread&lt;/b&gt; berjalan secara background untuk menangani jika ada perubahan pada &lt;b&gt;UI&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;@Background &lt;/b&gt;: annotation yang menunjukkan sebuah method berjalan di thread selain ui thread.&lt;br /&gt;
&lt;b&gt;@UiThread&lt;/b&gt; : annotation yang menunjukkan sebuah method berjalan di thread ui.&lt;br /&gt;
&lt;br /&gt;
Contoh penggunaan annotation &lt;b&gt;@Background&lt;/b&gt; yaitu untuk melakukan proses request data ke REST API. Kemudian respon yang diterima di jalankan di &lt;b&gt;@UiThread&lt;/b&gt; sehingga UI ter-update.&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;@Background
void requestPost(String id) {
    Post post = apiService.getPost(id);
    updateViews(post);
}

@UiThread
void updateViews(Post post) {
    progressDialog.dismiss();

    if(post == null) {
        Toast.makeText(this, "Cannot load data", Toast.LENGTH_SHORT).show();
        return;
    }

    postTitle.setText(post.getTitle());
    postBody.setText(post.getBody());
}
&lt;/pre&gt;
Nah setelah saya menjelaskan panjang lebar di atas, mari kita ke tahap implementasi selanjutnya.&lt;br /&gt;
&lt;br /&gt;
Buat kelas POJOS sebagai berikut.
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package com.wimso.android_aa.model;

/**
 * Created by Wim on 9/21/16.
 */
public class Post {

    private int userId;
    private int id;
    private String title;
    private String body;

    public int getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }
}

&lt;/pre&gt;
Lengkapi source code MainActivity berikut :
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package com.wimso.android_aa;

import android.app.ProgressDialog;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.wimso.android_aa.model.Post;
import com.wimso.android_aa.network.ApiService;

import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.Background;
import org.androidannotations.annotations.Click;
import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.UiThread;
import org.androidannotations.annotations.ViewById;
import org.androidannotations.rest.spring.annotations.RestService;

@EActivity(R.layout.activity_main)
public class MainActivity extends AppCompatActivity {

    @ViewById(R.id.post_text) EditText postText;
    @ViewById(R.id.post_title) TextView postTitle;
    @ViewById(R.id.post_body) TextView postBody;

    @RestService ApiService apiService;

    private ProgressDialog progressDialog;

    @AfterViews
    public void bindViews() {
        // Default Text
        postText.setText("1");

        progressDialog = new ProgressDialog(this);
        progressDialog.setMessage("Loading...");
        progressDialog.setCancelable(true);
    }

    @Click(R.id.btn_post)
    void getPostClicked() {
        progressDialog.show();

        if(!TextUtils.isEmpty(postText.getText())) {
            requestPost(postText.getText().toString());
        }
    }

    @Background
    void requestPost(String id) {
        Post post = apiService.getPost(id);
        updateViews(post);
    }

    @UiThread
    void updateViews(Post post) {
        progressDialog.dismiss();

        if(post == null) {
            Toast.makeText(this, "Cannot load data", Toast.LENGTH_SHORT).show();
            return;
        }

        postTitle.setText(post.getTitle());
        postBody.setText(post.getBody());
    }

}
&lt;/pre&gt;
Setelah itu, Build → Make Project. Maka Android Studio akan men-generate kelas MainActivity menjadi subclass dengan nama MainActivity_. Setiap subclass memiliki nama yang sama dengan tambahan sufix &lt;b&gt;_&lt;/b&gt; (undescore).&lt;br /&gt;
&lt;br /&gt;
Langkah terakhir adalah register MainActivity di AndroidManifest.xml. Activity yang diregister adalah subclassnya yang terdapat suffix &lt;b&gt;_&lt;/b&gt; (undescore).
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.wimso.android_aa"&amp;gt;

    &amp;lt;uses-permission android:name="android.permission.INTERNET"/&amp;gt;

    &amp;lt;application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"&amp;gt;
        &amp;lt;activity android:name=".MainActivity_"&amp;gt;
            &amp;lt;intent-filter&amp;gt;
                &amp;lt;action android:name="android.intent.action.MAIN" /&amp;gt;

                &amp;lt;category android:name="android.intent.category.LAUNCHER" /&amp;gt;
            &amp;lt;/intent-filter&amp;gt;
        &amp;lt;/activity&amp;gt;
    &amp;lt;/application&amp;gt;

&amp;lt;/manifest&amp;gt;
&lt;/pre&gt;
Selesai, build dan jalankan maka hasilnya sebagai berikut :
&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-RstA9ZL_AQ9Z_togEwrNr6fbkxLy7aV_0XFdHwK-k8-R9CASsJCMxQKVEhVhlzhJqIgANQHX909rrec-UFzMKqbSzVeGcvwtbee_4rlx74x432np12NwQ3XbWDYbiBOY_MBj7Un2WuU/s1600/device-2016-09-21-210127.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-RstA9ZL_AQ9Z_togEwrNr6fbkxLy7aV_0XFdHwK-k8-R9CASsJCMxQKVEhVhlzhJqIgANQHX909rrec-UFzMKqbSzVeGcvwtbee_4rlx74x432np12NwQ3XbWDYbiBOY_MBj7Un2WuU/s400/device-2016-09-21-210127.png" width="225" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Source code lengkap dapat dilihat di &lt;a href="https://github.com/wimsonevel/Android-AA"&gt;https://github.com/wimsonevel/Android-AA&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Sekian tutorial kali ini. Terima kasih sudah menyimak.&lt;br /&gt;
Semoga bermanfaat. :)</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFL1-cvfmVu8kOC9YIOAoQqKjBYcRzOFmxIzJlU219Bly0UGNPZhteQCv6pifUPZ2F3gGcwEluBvCH0TcjUGmLmkkvt3KEp1Mz4Kb1WnRZPS7U0rRhOjX6bAXLf7m-FMBjnFJ7T4J85g8/s72-c/android-annotations.png" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>(Tutorial Android) Data Binding in Android</title><link>http://wimsonevel.blogspot.com/2016/08/tutorial-android-data-binding-in-android.html</link><category>Android</category><author>noreply@blogger.com (Wim Sonevel)</author><pubDate>Sat, 27 Aug 2016 20:16:00 +0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-6966757688576433754.post-5155860268817704755</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOEkZTvubQd_eStMDrHfwhOEm-tCP-rv8RBV2gUbPD7j8rQOFj3gqUAgAj0zURAKj-dtr5ztdiejPG502foC2WPLzh3xg9fnlsGG8S1dED2E5jkAj-nUQdeTsvkFJxRgCKNiItyc0gXjs/s1600/android-databinding.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOEkZTvubQd_eStMDrHfwhOEm-tCP-rv8RBV2gUbPD7j8rQOFj3gqUAgAj0zURAKj-dtr5ztdiejPG502foC2WPLzh3xg9fnlsGG8S1dED2E5jkAj-nUQdeTsvkFJxRgCKNiItyc0gXjs/s640/android-databinding.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;b&gt;Data Binding&lt;/b&gt; merupakan sebuah teknik yang menyatukan dan menghubungkan antara komponen UI dengan data source. Konsep dari Data Binding yaitu setiap kali terdapat perubahan pada data source, maka komponen UI otomatis akan berubah. Data Binding Library di Android mulai diperkenalkan oleh Google pada event Google I/O 2015. 
&lt;br /&gt;
&lt;br /&gt;
Sebelumnya adanya &lt;b&gt;Data Binding Library&lt;/b&gt;, memanggil komponen UI Layout ke Activity atau Fragment dengan cara sederhana yang biasanya kita gunakan seperti memanggil komponen UI dengan &lt;b&gt;findViewById&lt;/b&gt;, membuat variabel local untuk view terlebih dahulu kemudian mengambil nilai ataupun mengeset nilai. 
&lt;br /&gt;
&lt;br /&gt;
Cara yang sederhana ini memang terkesan manual dan membuat banyak code yang diulang sehingga source code menjadi banyak dan tidak efisien, apalagi kalau berhubungan dengan layout yang kompleks. &lt;br /&gt;
&lt;br /&gt;
Nah, dengan teknik Data Binding kita membuat aplikasi dengan cepat dan ringkas.&lt;br /&gt;
&lt;br /&gt;
Bye... findViewById().&lt;br /&gt;
&lt;br /&gt;
Pada tutorial kali ini saya akan menjelaskan implementasi Data Binding Library di Android. 

Data Binding Library merupakan support library yang sangat fleksibel, kita dapat menerapkannya mulai dari versi Android 2.1.&lt;br /&gt;
&lt;br /&gt;
Pertama kita mulai mengkonfigurasikan data binding di gradle dengan code berikut :
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;android {
    ...
    dataBinding {
        enabled = true
    }
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Membuat Layout&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Layout dengan menggunakan Data Binding berbeda dengan layout tanpa Data Binding. Tag root pada layout di awali dengan tag &lt;b&gt;&amp;lt;layout&amp;gt;&lt;/b&gt; dan untuk mendefinisikan data model menggunakan tag &lt;b&gt;&amp;lt;data&amp;gt;&lt;/b&gt; dan tag &lt;b&gt;&amp;lt;variable&amp;gt;&lt;/b&gt; di dalamnya. Mengubah ataupun Mengeset properti pada layout dengan menggunakan sintak "&lt;b&gt;@{}&lt;/b&gt;".&lt;br /&gt;
&lt;br /&gt;
Berikut contohnya :
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;layout xmlns:android="http://schemas.android.com/apk/res/android" &amp;gt;

    &amp;lt;data&amp;gt;
      &amp;lt;variable
            name="user"
            type="example.wimsonevel.androiddatabinding.model.User" /&amp;gt;
       
 &amp;lt;variable
            name="handler"
            type="example.wimsonevel.androiddatabinding.EventHandler" /&amp;gt;
    &amp;lt;/data&amp;gt;

    &amp;lt;LinearLayout
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context="example.wimsonevel.androiddatabinding.MainActivity"&amp;gt;

        &amp;lt;ImageView
            android:id="@+id/img_profile"
            android:layout_width="match_parent"
            android:layout_height="200dp"
            android:scaleType="centerCrop"
            android:src="@{user.picture}"/&amp;gt;

        &amp;lt;TextView
            android:id="@+id/tv_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:layout_marginTop="8dp"
            android:layout_marginLeft="8dp"
            android:layout_marginRight="8dp"
            android:text="@{user.name}"/&amp;gt;

        &amp;lt;TextView
            android:id="@+id/tv_email"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:layout_margin="8dp"
            android:text="@{user.email}"/&amp;gt;

        &amp;lt;Button
            android:id="@+id/btn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="More"
            android:layout_margin="8dp"
            android:onClick="@{handler.clicked}"/&amp;gt;

    &amp;lt;/LinearLayout&amp;gt;
&amp;lt;/layout&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Data Model&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Berikutnya adalah mendefinisikan data modelnya. Pada umumnya, kelas &lt;b&gt;POJO&lt;/b&gt; (Plain Old Java Object) dapat digunakan untuk Data Binding. Akan tetapi, kita harus memodifikasi bagian tertentu agar data dapat berpengaruh pada UI. 
&lt;br /&gt;
&lt;br /&gt;
Android menyediakan kelas &lt;b&gt;BaseObservable&lt;/b&gt; yang dapat kita &lt;i&gt;extend&lt;/i&gt; ke kelas POJO sehingga dapat menyesuaikan ketika terjadi perubahan pada data. &lt;br /&gt;
&lt;br /&gt;
Berikut contoh kelas &lt;b&gt;User.java &lt;/b&gt;
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package example.wimsonevel.androiddatabinding.model;

import android.databinding.BaseObservable;
import android.databinding.Bindable;
import android.databinding.BindingAdapter;
import android.graphics.drawable.Drawable;
import android.widget.ImageView;
import example.wimsonevel.androiddatabinding.BR;

/**
 * Created by Wim on 8/21/16.
 */
public class User extends BaseObservable {

    private Drawable picture;
    private String name;
    private String email;

    @Bindable
    public Drawable getPicture() {
        return picture;
    }

    public void setPicture(Drawable picture) {
        this.picture = picture;
        notifyPropertyChanged(BR.picture);
    }

    @Bindable
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
        notifyPropertyChanged(BR.name);
    }

    @Bindable
    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
        notifyPropertyChanged(BR.email);
    }

}
&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style="font-size: large;"&gt;Binding Data&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Kelas Binding otomatis di generate sesuai dengan nama layout. Misalnya nama layoutnya “&lt;b&gt;activity_main.xml&lt;/b&gt;” maka kelas Binding terbentuk dengan nama “&lt;b&gt;ActivityMainBinding&lt;/b&gt;”. Kelas Binding ini ditandai dengan suffix “&lt;b&gt;Binding&lt;/b&gt;”. Berikut implemetasinya di MainActivity.java.
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package example.wimsonevel.androiddatabinding;
import android.databinding.DataBindingUtil;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import example.wimsonevel.androiddatabinding.databinding.ActivityMainBinding;
import example.wimsonevel.androiddatabinding.model.User;

public class MainActivity extends AppCompatActivity {

    ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        binding.setUser(user());
        binding.setHandler(new EventHandler());
    }

    private User user() {
        User user = new User();
        user.setName("Wim Sonevel");
        user.setEmail("wim.sonevel93@gmail.com");
        user.setPicture(ContextCompat.getDrawable(this, R.drawable.photo));

        return user;
    }
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style="font-size: large;"&gt;Event Handling&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Data Binding dapat digunakan untuk menangani event handling. Misalnya pada atribut &lt;b&gt;onclick&lt;/b&gt;.
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;Button
    android:id="@+id/btn"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="More"
    android:layout_margin="8dp"
    android:onClick="@{handler.clicked}"/&amp;gt;
&lt;/pre&gt;
Kemudian mendefinisikan kelas Handlernya :
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package example.wimsonevel.androiddatabinding;

import android.view.View;
/**
 * Created by Wim on 8/27/16.
 */
public class EventHandler {

    public void clicked(View view) {
        // Do something here
    }

}
&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style="font-size: large;"&gt;Binding in RecyclerView&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Data Binding juga dapat digunakan di RecyclerView. Kita dapat membuat Custom Adapter menggunakan Data Binding seperti berikut :
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package example.wimsonevel.androiddatabinding.adapter;

import android.databinding.DataBindingUtil;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.List;
import example.wimsonevel.androiddatabinding.R;
import example.wimsonevel.androiddatabinding.databinding.ItemListBinding;
import example.wimsonevel.androiddatabinding.model.Item;



/**
 * Created by Wim on 8/27/16.
 */
public class ListAdapter extends RecyclerView.Adapter&amp;lt;ListAdapter.ListViewHolder&amp;gt;{

    private List&amp;lt;Item&amp;gt; itemList;

    public ListAdapter(List&amp;lt;Item&amp;gt; itemList) {
        this.itemList = itemList;
    }

    @Override
    public ListViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list, parent, false);
        return new ListViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ListViewHolder holder, int position) {
        holder.bind(itemList.get(position));
    }

    @Override
    public int getItemCount() {
        return itemList.size();
    }

    static class ListViewHolder extends RecyclerView.ViewHolder {
        ItemListBinding binding;

        public ListViewHolder(View itemView) {
            super(itemView);
            binding = DataBindingUtil.bind(itemView);
        }

        void bind(Item item) {
            binding.setList(item);
            binding.executePendingBindings();
        }
    }

}
&lt;/pre&gt;
Pada ListViewHolder disini tempat kita menginstance kelas ItemListBinding. &lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;With Picasso or Glide&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Salah satu fitur penting di Data Binding Library adalah &lt;b&gt;BindingAdapter&lt;/b&gt;. &lt;b&gt;BindingAdapter&lt;/b&gt; adalah sebuah annotation yang memungkinkan kita untuk membuat custom atribut xml. Pada kasus ini misalkan kita ingin menampilkan image dari url menggunakan library image loader(Picasso atau Glide). Penggunaan BindingAdapter yakni dengan membuat sebuah method static kemudian mendefinisikan annotation &lt;b&gt;@BindingAdapter&lt;/b&gt;. Contohnya berikut :
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;private String imgUrl;

public String getImgUrl() {
    return imgUrl;
}

@BindingAdapter({"bind:imageUrl"})
public static void setImageUrlWithPicasso(ImageView imageView, String imageUrl) {
    Picasso.with(imageView.getContext())
            .load(imageUrl)
            .into(imageView);
}
&lt;/pre&gt;
&lt;b&gt;bind:imageUrl&lt;/b&gt; merupakan custom atribut xml yang akan dipanggil di layout.&lt;br /&gt;
&lt;br /&gt;
Lalu, di layout kita tinggal memanggil atribut tersebut sepert ini :
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;...
&amp;lt;ImageView
    android:id="@+id/img_profile"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:scaleType="centerCrop"
    app:imageUrl="@{user.imgUrl}"/&amp;gt;
...
&lt;/pre&gt;
Terakhir adalah mencoba menjalankan app yang kita buat dengan Data Binding. Maka hasilnya seperti berikut :&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhevUzQaKuG2UonEDgD3_r1zQhnOFlV7g-gSMp0CRtinu5RmwsmpTxziLDnvuvzkrhmcNEeordC0KBF3gRoTZtYUW4xke-MCEcVdnudpxLhxvXX0kzGMwHWQa4c_sj_ufWsMUpTlUvXDu8/s1600/device-2016-08-27-172650.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhevUzQaKuG2UonEDgD3_r1zQhnOFlV7g-gSMp0CRtinu5RmwsmpTxziLDnvuvzkrhmcNEeordC0KBF3gRoTZtYUW4xke-MCEcVdnudpxLhxvXX0kzGMwHWQa4c_sj_ufWsMUpTlUvXDu8/s400/device-2016-08-27-172650.png" width="225" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxJ1ST1kv_F-QysMq9rgUabzJmOczysislTmVOHYrj2bBkQcq5CsEYJ1laZpR7vCMNA7e3zlT4uO67RY341DEASElNe5EQ6Ge_6Sd22-LaNDE4kxhdSdfG0bCfWA56Nso-z20hPlggfM0/s1600/device-2016-08-27-172727.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxJ1ST1kv_F-QysMq9rgUabzJmOczysislTmVOHYrj2bBkQcq5CsEYJ1laZpR7vCMNA7e3zlT4uO67RY341DEASElNe5EQ6Ge_6Sd22-LaNDE4kxhdSdfG0bCfWA56Nso-z20hPlggfM0/s400/device-2016-08-27-172727.png" width="225" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Untuk &lt;b&gt;Source code&lt;/b&gt; lengkapnya dapat dilihat di&amp;nbsp;&lt;a href="https://github.com/wimsonevel/AndroidDataBinding"&gt;https://github.com/wimsonevel/AndroidDataBinding&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Sekian dari saya dan semoga bermanfaat.&lt;br /&gt;
Terima Kasih ^^
</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOEkZTvubQd_eStMDrHfwhOEm-tCP-rv8RBV2gUbPD7j8rQOFj3gqUAgAj0zURAKj-dtr5ztdiejPG502foC2WPLzh3xg9fnlsGG8S1dED2E5jkAj-nUQdeTsvkFJxRgCKNiItyc0gXjs/s72-c/android-databinding.png" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>(Tutorial Android) Dependency Injection in Android with Dagger 2</title><link>http://wimsonevel.blogspot.com/2016/08/tutorial-android-dependency-injection.html</link><category>Android</category><author>noreply@blogger.com (Wim Sonevel)</author><pubDate>Sun, 14 Aug 2016 18:05:00 +0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-6966757688576433754.post-64735200020926693</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAgeF6hUQhjAf85ZQhRJ_-KK9198HByU1O_yPhk-8dB23jU8SL8fwlYAMSQedwakVE4s9i_49DLFom7j0-lbppvhfdKgPpmJhA5Xur-4XkNLgIeqhak-GYV7YmPpdXdPk9G7LBdx1of90/s1600/android-dagger2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAgeF6hUQhjAf85ZQhRJ_-KK9198HByU1O_yPhk-8dB23jU8SL8fwlYAMSQedwakVE4s9i_49DLFom7j0-lbppvhfdKgPpmJhA5Xur-4XkNLgIeqhak-GYV7YmPpdXdPk9G7LBdx1of90/s640/android-dagger2.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;b&gt;Dependency Injection &lt;/b&gt;atau biasa disingkat &lt;b&gt;DI&lt;/b&gt; adalah sebuah konsep dalam software design pattern yang berfokus untuk menjadikan aplikasi lebih &lt;i&gt;loosely coupled&lt;/i&gt;, &lt;i&gt;extensible&lt;/i&gt;, dan &lt;i&gt;maintainable&lt;/i&gt;. Artinya, dalam pembuatan aplikasi menjadi lebih rapi, mudah dipahami dan dikelola. Dengan konsep DI ini bertujuan agar suatu kelas tidak terikat dengan kelas lain dan bagian-bagian code menjadi longgar (loosely coupled). Fungsi dari DI sendiri yaitu menginjeksi bagian-bagian tertentu dalam aplikasi sehingga dapat mempermudah mengatur flow sebuah program. Konsep ini sering juga disebut &lt;i&gt;Inversion of Control&lt;/i&gt;.
&lt;br /&gt;
&lt;br /&gt;
Jadi intinya, dengan dependency injection kita dapat menginjeksi kelas-kelas tertentu ke kelas yang membutuhkan dependency.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Dagger 2&lt;/b&gt; merupakan library dependency injection untuk Android dan Java. Dagger 2 berbasis &lt;b&gt;Java Specification Request (JSR) 330&lt;/b&gt; yang merupakan standar Java Annotations. Dagger 2 benar-benar hasil dari code generation dan bukan merupakan refleksi seperti library lainnya sehingga penggunaan menjadi lebih efisien. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Dagger 2&lt;/b&gt; terdapat beberapa annotation diantaranya :&lt;br /&gt;
- &lt;b&gt;@Module&lt;/b&gt; : mendefinisikan kelas yang menyediakan dependencies&lt;br /&gt;
- &lt;b&gt;@Provides&lt;/b&gt; : mendefinisikan method-method yang ada di kelas&amp;nbsp;&lt;b&gt;@Module&lt;/b&gt;&lt;br /&gt;
- &lt;b&gt;@Inject&lt;/b&gt; :  mendefinisikan sebuah request dependency, bisa berupa konstruktor, method, maupun field&lt;br /&gt;
- &lt;b&gt;@Component&lt;/b&gt; : mendefinisikan sebuah jembatan penghubung antara module dan injection.&lt;br /&gt;
&lt;br /&gt;
Pada postingan kali ini saya ingin mencoba menjelaskan implementasi Dependency Injection di Android dengan menggunakan library Dagger 2.&lt;br /&gt;
&lt;br /&gt;
Mengenai Dagger 2 selengkapnya bisa dilihat di &lt;a href="http://google.github.io/dagger/%C2%A0"&gt;http://google.github.io/dagger/&amp;nbsp;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Terlebih dahulu kita harus menambahkan library dagger di Gradle.
&lt;br /&gt;
&lt;br /&gt;
Top-Level
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;dependencies {
    classpath 'com.android.tools.build:gradle:2.0.0'
    classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
    // NOTE: Do not place your application dependencies here; they belong
    // in the individual module build.gradle files
}
&lt;/pre&gt;
Module-Level
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;apply plugin: 'com.neenbedankt.android-apt'
…

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'

    compile 'com.android.support:appcompat-v7:23.3.0'
    compile 'com.google.dagger:dagger:2.5'
    apt 'com.google.dagger:dagger-compiler:2.5'
    provided 'javax.annotation:jsr250-api:1.0'
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;Step 1 : Membuat kelas Object Dependent&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
Buat kelas dengan nama &lt;b&gt;User.java
&lt;/b&gt;&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package example.wim.androiddagger2;
import javax.inject.Inject;

/**
 * Created by Wim on 8/12/16.
 */
public class User {

    private String id;
    private String firstName;
    private String lastName;

    public User() {
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    @Override
    public String toString() {
        return "[id = " +id+ ", firstName = " + firstName + ", lastName = " + lastName + "]";
    }

}
&lt;/pre&gt;
Selanjutnya buat kelas &lt;b&gt;UserService.java&lt;/b&gt;. Kelas ini yang akan menyediakan dependencies.
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package example.wim.androiddagger2;

/**
 * Created by Wim on 8/12/16.
 */
public class UserService {

    private User user;

    public UserService(User user) {
        this.user = user;
    }

    public void addNewUser(String id, String firstname, String lastname) {
        user.setId(id);
        user.setFirstName(firstname);
        user.setLastName(lastname);
    }

    public User getUser() {
        return user;
    }

}
&lt;/pre&gt;
&lt;b&gt;Step 2 : Membuat kelas Module&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
Selanjutnya kita akan membuat kelas-kelas module yaitu &lt;b&gt;AppModule&lt;/b&gt; dan &lt;b&gt;UserModule&lt;/b&gt;.
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package example.wim.androiddagger2;

import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;

/**
 * Created by Wim on 8/12/16.
 */
@Module
public class AppModule {

    private Application application;

    public AppModule(Application application) {
        this.application = application;
    }

    @Provides
    @Singleton
    Context provideApplicationContext() {
        return application.getApplicationContext();
    }

    @Provides
    @Singleton
    SharedPreferences provideSharedPref() {
        return PreferenceManager.getDefaultSharedPreferences(application);
    }
}
&lt;/pre&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package example.wim.androiddagger2;

import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;

/**
 * Created by Wim on 8/12/16.
 */
@Module
public class UserModule {

    @Provides
    @Singleton
    public UserService provideUserService() {
        return new UserService(new User());
    }

}
&lt;/pre&gt;
&lt;b&gt;Step 3 : Membuat kelas Component sebagai penghubungkan antara Module dengan Injection&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
Buat kelas &lt;b&gt;Dagger Component&lt;/b&gt;. 
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package example.wim.androiddagger2;

import javax.inject.Singleton;
import dagger.Component;

/**
 * Created by Wim on 8/7/16.
 */
@Singleton
@Component(modules = {AppModule.class, UserModule.class})
public interface DiComponent {

    void inject(MainActivity activity);

}
&lt;/pre&gt;
Sampai disini, &lt;b&gt;rebuild project&lt;/b&gt; terlebih dahulu agar otomatis ter-generate kelas &lt;b&gt;DaggerDiComponent&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
Buat kelas Application dan instance kelas &lt;b&gt;DiComponent&lt;/b&gt; yang memberikan dependency injection, kemudian kita dapat mengaksesnya melalui method &lt;b&gt;getComponent&lt;/b&gt;.
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package example.wim.androiddagger2;
import android.app.Application;

/**
 * Created by Wim on 8/7/16.
 */
public class MainApp extends Application {

    DiComponent component;

    @Override
    public void onCreate() {
        super.onCreate();
        component = DaggerDiComponent.builder()
                .appModule(new AppModule(this))
                .build();
    }

    public DiComponent getComponent() {
        return component;
    }

}
&lt;/pre&gt;
Sekarang kita telah memiliki setiap koneksi kelasnya. Di kelas &lt;b&gt;MainActivity&lt;/b&gt;, gunakan annotation &lt;b&gt;@Inject&lt;/b&gt; untuk mengambil dependencies.
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package example.wim.androiddagger2;

import android.content.SharedPreferences;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

import javax.inject.Inject;

public class MainActivity extends AppCompatActivity {

    @Inject
    UserService userService;

    @Inject
    SharedPreferences sharedPref;

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

        TextView message = (TextView) findViewById(R.id.message);

        ((MainApp) getApplication()).getComponent().inject(this);

        userService.addNewUser("1", "Wim", "Sonevel");

        sharedPref.edit()
                .putString(userService.getUser().getId(), userService.getUser().toString())
                .apply();

        message.setText("New User Inserted : " + sharedPref.getString(userService.getUser().getId()
, ""));

    }
}
&lt;/pre&gt;
Sekarang build dan jalankan, maka hasilnya sebagai berikut :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-b2Yx0jp-x6MDJn6EKcWgd3gHidmfGCVIiKTojIV-SMbZl0TMTnXyvBfmLkw8HTfafDu_IpbcyXXCZdH1YgS4M9o_3EVny6LhPa8D9TVDToaSpQE0OlpmPs3gza0m_hk0B3BIT40niMk/s1600/device-2016-08-14-174810.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-b2Yx0jp-x6MDJn6EKcWgd3gHidmfGCVIiKTojIV-SMbZl0TMTnXyvBfmLkw8HTfafDu_IpbcyXXCZdH1YgS4M9o_3EVny6LhPa8D9TVDToaSpQE0OlpmPs3gza0m_hk0B3BIT40niMk/s400/device-2016-08-14-174810.png" width="225" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Source code lengkap dapat dilihat di &lt;a href="https://github.com/wimsonevel/Android-Dagger2"&gt;https://github.com/wimsonevel/Android-Dagger2&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Sekian tutorial kali ini, semoga bermanfaat.&lt;br /&gt;
Terima kasih.&lt;br /&gt;
&lt;br /&gt;
Happy Coding. ^^</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAgeF6hUQhjAf85ZQhRJ_-KK9198HByU1O_yPhk-8dB23jU8SL8fwlYAMSQedwakVE4s9i_49DLFom7j0-lbppvhfdKgPpmJhA5Xur-4XkNLgIeqhak-GYV7YmPpdXdPk9G7LBdx1of90/s72-c/android-dagger2.png" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">5</thr:total></item><item><title>(Tutorial iOS) Sidebar Menu with SWRevealViewController in Swift</title><link>http://wimsonevel.blogspot.com/2016/08/tutorial-ios-sidebar-menu-with.html</link><category>iOS</category><category>Swift</category><author>noreply@blogger.com (Wim Sonevel)</author><pubDate>Sun, 7 Aug 2016 01:41:00 +0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-6966757688576433754.post-3371305952831884765</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRLFGlWnOo-onvLUD6nkB2OjWA8R5gHIRCVYVfkwZvu1SEzaNcWLvGWNTEIW3traUQoo-x326R-iQVa0amJYNC9b__AYT_p5SDeXqnugpt-UyzaAdn0LNRDa_UKNkQsmzhSsci-7K6iBE/s1600/ios+sidebar.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="800" data-original-width="1280" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRLFGlWnOo-onvLUD6nkB2OjWA8R5gHIRCVYVfkwZvu1SEzaNcWLvGWNTEIW3traUQoo-x326R-iQVa0amJYNC9b__AYT_p5SDeXqnugpt-UyzaAdn0LNRDa_UKNkQsmzhSsci-7K6iBE/s640/ios+sidebar.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;b&gt;SWRevealViewController&lt;/b&gt; merupakan sebuah UIViewController yang dapat digunakan untuk membuat menu samping (sidebar menu) di iOS. Side View bisa diletakkan di kiri maupun di kanan. Jadi, &lt;b&gt;SWRevealViewController&lt;/b&gt; ini mirip dengan Sidebar menu pada aplikasi Facebook.
&lt;br /&gt;
&lt;div style="line-height: 100%; margin-bottom: 0in;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="line-height: 100%; margin-bottom: 0in;"&gt;
Contohnya seperti
ini :&lt;/div&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixNDO1-rtjNX5AxL8qdSsnTuMx_JR_6xjDWCqAGNbRGTf3HkttgtCLs3cpmX2TUXN7dMpJNQPP0UtStLpUsaiIkG7tnhWpc46G85zGQJz8SgugxYkKDePXDchdOm7OvINYaACJhkXGeVg/s1600/facebook+sidebar.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="296" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixNDO1-rtjNX5AxL8qdSsnTuMx_JR_6xjDWCqAGNbRGTf3HkttgtCLs3cpmX2TUXN7dMpJNQPP0UtStLpUsaiIkG7tnhWpc46G85zGQJz8SgugxYkKDePXDchdOm7OvINYaACJhkXGeVg/s400/facebook+sidebar.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Sidebar sendiri secara default sebenarnya tidak ada di iOS. Namun, kita bisa membuat atau mengcustom sendiri sidebar menu dengan bantuan library SWRevealViewController.&lt;br /&gt;
&lt;br /&gt;
Pada postingan kali ini saya mau membahas bagaimana cara membuat Sidebar Navigation Menu di iOS.&lt;br /&gt;
&lt;br /&gt;
Sebelumnya kita harus mendownload dulu SWRevealViewController library di sini &lt;a href="https://github.com/John-Lluch/SWRevealViewController%C2%A0"&gt;https://github.com/John-Lluch/SWRevealViewController&amp;nbsp;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Hanya ada 2 buah file yang kita butuhkan yakni :&lt;br /&gt;
&lt;b&gt;- SWRevealViewController.h&amp;nbsp;&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;- SWRevealViewController.m&amp;nbsp;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Kemudian buat project baru di XCODE, lalu masukkan import kedua file &lt;b&gt;SWRevealViewController.h&lt;/b&gt; dan &lt;b&gt;SWRevealViewController.m&lt;/b&gt; ke folder SideBar.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfDq05FMsAddJgMrRw7Y-ti8P3xYWwr1IGxcvK_LYK85ZXmUVJNk8mlWwih6NsSwEj2TV_Du-2fTV32VRRTllD_Txkh_UCRJnkaeWWfeN8vICqDaTMc0B6HMk78TfQv3o-sU1RPOhj_5Y/s1600/Screen+Shot+2016-08-06+at+8.29.28+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfDq05FMsAddJgMrRw7Y-ti8P3xYWwr1IGxcvK_LYK85ZXmUVJNk8mlWwih6NsSwEj2TV_Du-2fTV32VRRTllD_Txkh_UCRJnkaeWWfeN8vICqDaTMc0B6HMk78TfQv3o-sU1RPOhj_5Y/s400/Screen+Shot+2016-08-06+at+8.29.28+PM.png" width="238" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Pada saat diimport biasanya akan muncul alert untuk menambahkan &lt;b&gt;Bridging Header&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
Apa itu &lt;b&gt;Bridging Header&lt;/b&gt;? 
&lt;b&gt;Bridging Header&lt;/b&gt; berfungsi sebagai penghubung atau jembatan komunikasi antara &lt;b&gt;Objective-C&lt;/b&gt; ke &lt;b&gt;Swift&lt;/b&gt;. Jadi, kita dapat memanggil kelas &lt;b&gt;Objective-C&lt;/b&gt; ke dalam kelas &lt;b&gt;Swift&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
Download icon-icon (&lt;b&gt;menu, home, profile, notifications, star dan settings&lt;/b&gt;) yang dibutuhkan dan bisa dicari di :&amp;nbsp;&lt;a href="https://design.google.com/icons/"&gt;https://design.google.com/icons/&lt;/a&gt;&lt;br /&gt;
Kemudian taruh di &lt;b&gt;assets/Images&lt;/b&gt;.
&lt;br /&gt;
&lt;br /&gt;
File Bridging Header nantinya akan otomatis di tambahkan. Untuk mengecek apakah sudah terpasang atau belum bisa dilihat di tab &lt;b&gt;Build Settings&lt;/b&gt; di project.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEZRwY1mSYsJ3JIjUH77aatkwVJvkxOowbK1O2YyqTlugkjXtQaREoJk9AIuDLCd6EHYsSsVTqqbk3OMN9N2btTOHh45Qd_aqo2XZOUVdTtlkQ12HYcoQudBFeqiGbcoWlZTkmV7XxVQo/s1600/Screen+Shot+2016-08-06+at+8.44.38+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="278" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEZRwY1mSYsJ3JIjUH77aatkwVJvkxOowbK1O2YyqTlugkjXtQaREoJk9AIuDLCd6EHYsSsVTqqbk3OMN9N2btTOHh45Qd_aqo2XZOUVdTtlkQ12HYcoQudBFeqiGbcoWlZTkmV7XxVQo/s640/Screen+Shot+2016-08-06+at+8.44.38+PM.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Selanjutnya mendesain Storyboard sebagai berikut :&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQdH5fPRUXZMaIfZPnr0DcyRscScy_gkS1GKQpV1aKvqd_1CIdIE2BvJRn5vjQPh7HijyhRA1rfEqSKsaXb9eTApkLe2knBF2ZWZqZbVB33yRKzTIvOdKt2wHO7_zVhWIqIrtUyJrJqqQ/s1600/Screen+Shot+2016-08-06+at+8.47.59+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="334" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQdH5fPRUXZMaIfZPnr0DcyRscScy_gkS1GKQpV1aKvqd_1CIdIE2BvJRn5vjQPh7HijyhRA1rfEqSKsaXb9eTApkLe2knBF2ZWZqZbVB33yRKzTIvOdKt2wHO7_zVhWIqIrtUyJrJqqQ/s640/Screen+Shot+2016-08-06+at+8.47.59+PM.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
*Sorry gan screenshotnya terpotong di bagian bawah alias gak muat.&lt;br /&gt;
&lt;br /&gt;
Pada Main.Storyboard terdiri dari :&lt;br /&gt;
&lt;b&gt;1. RevealViewController&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;2. SideMenuController&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;3. HomeViewController&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;4. ProfileViewController&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;5. NotificationsViewController&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;6. FavoritesViewController&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;7. SettingsViewController&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Pada desain Storyboard di atas kita harus menambahkan Custom UIViewController dengan &lt;b&gt;SWRevealViewController&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKFJaaMwnbiv2pzaV3Rq6WeP3e0j_XTw3NgzZGe5Q25i7GF3YWyaLMNsxOcQfkmdeVuM03hGQlTbeyFYDFMO019tIOsHS-vlGQYwF8vHRZ248uuyfWvuxZxbuPqwSFeCOOEWgPxj7n7cg/s1600/Screen+Shot+2016-08-06+at+8.50.15+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="304" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKFJaaMwnbiv2pzaV3Rq6WeP3e0j_XTw3NgzZGe5Q25i7GF3YWyaLMNsxOcQfkmdeVuM03hGQlTbeyFYDFMO019tIOsHS-vlGQYwF8vHRZ248uuyfWvuxZxbuPqwSFeCOOEWgPxj7n7cg/s640/Screen+Shot+2016-08-06+at+8.50.15+PM.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Setting dan tambahkan 2 custom segue yang satunya ke UIViewController untuk Home (sw_front). &lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitiy_kcEuHOf27nW4bNob5pAHTISAbMmuJEHnZBYhs_qnoFOPigIVkrAzeRY0QdWh1usW2NKrrWozW8b_yb5AFJcrxfosygAqF29RLotADJ9k1oc-y9WXDoTYq6KXOz6UHn29f860dIaM/s1600/Screen+Shot+2016-08-06+at+8.53.15+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitiy_kcEuHOf27nW4bNob5pAHTISAbMmuJEHnZBYhs_qnoFOPigIVkrAzeRY0QdWh1usW2NKrrWozW8b_yb5AFJcrxfosygAqF29RLotADJ9k1oc-y9WXDoTYq6KXOz6UHn29f860dIaM/s320/Screen+Shot+2016-08-06+at+8.53.15+PM.png" width="311" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7B8ZIH7nh9kUNy1sVSkyboYTVuXoU8d0t94rzZ9ABsjFmliEB_46uGbGD0wj7T_6eCqWCKPEE1TRiiBEm-QZuKOWMmI3G9syqMisQKRk1Gjt2W4EGUgIrwHvCPCWYC69P1nXoRByOs5k/s1600/Screen+Shot+2016-08-06+at+8.55.13+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="145" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7B8ZIH7nh9kUNy1sVSkyboYTVuXoU8d0t94rzZ9ABsjFmliEB_46uGbGD0wj7T_6eCqWCKPEE1TRiiBEm-QZuKOWMmI3G9syqMisQKRk1Gjt2W4EGUgIrwHvCPCWYC69P1nXoRByOs5k/s400/Screen+Shot+2016-08-06+at+8.55.13+PM.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Dan yang kedua untuk SideMenuController. Masing-masing di setting class &lt;b&gt;SWRevealViewControllerSegueSetController&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmlDjNcP-my03lYvRc1Sw6vRlRtrPBpt6EH9VSAf7j0ypTF1HSkOX1oKHvaZnHLy0XoiMyrjteM-_Hnnp9z4cfqtpIYvBIrHlPXKZeXRNzYFa2gFSDWaCpXHmvQHVo3xc8qG3SGGnfJ2A/s1600/Screen+Shot+2016-08-06+at+8.56.41+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="209" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmlDjNcP-my03lYvRc1Sw6vRlRtrPBpt6EH9VSAf7j0ypTF1HSkOX1oKHvaZnHLy0XoiMyrjteM-_Hnnp9z4cfqtpIYvBIrHlPXKZeXRNzYFa2gFSDWaCpXHmvQHVo3xc8qG3SGGnfJ2A/s320/Screen+Shot+2016-08-06+at+8.56.41+PM.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjho6CrYKMYtIrl7GGjn_Jg36our3guuMykqlYPqNJuBPwy2-mTpl3ZX3Q2oFOI7eIxuF8Q2Wrn2BDFh7De3GKMTFlqeJmvrOIHFtKPYI5VjDpyqAQwxnrCtqp2hH-rGiFW60lov2Qr7rg/s1600/Screen+Shot+2016-08-06+at+8.57.08+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="135" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjho6CrYKMYtIrl7GGjn_Jg36our3guuMykqlYPqNJuBPwy2-mTpl3ZX3Q2oFOI7eIxuF8Q2Wrn2BDFh7De3GKMTFlqeJmvrOIHFtKPYI5VjDpyqAQwxnrCtqp2hH-rGiFW60lov2Qr7rg/s400/Screen+Shot+2016-08-06+at+8.57.08+PM.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Kemudian dari SideMenuController hubungkan masing-masing ke HomeViewController, ProfileViewController, NotificationsViewController, FavoritesViewController dan SettingsViewController dengan custom segue.
&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAmRt9GKyVNNTs_dCcBIejS6uI-BEcS5sOiOjn68KjpUX6vIj1gn_pEAXl3bWysPkWsaS3r5ysc5crcsezRprwvma9iW0Oef4e3SLWTUzq4ih-Oxnrhi143g5N-lz7j5Qu2jqndcPKjxE/s1600/Screen+Shot+2016-08-06+at+9.03.45+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAmRt9GKyVNNTs_dCcBIejS6uI-BEcS5sOiOjn68KjpUX6vIj1gn_pEAXl3bWysPkWsaS3r5ysc5crcsezRprwvma9iW0Oef4e3SLWTUzq4ih-Oxnrhi143g5N-lz7j5Qu2jqndcPKjxE/s1600/Screen+Shot+2016-08-06+at+9.03.45+PM.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Lalu di set class &lt;b&gt;SWRevealViewControllerSeguePushController&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnxmTMV5NbmHfjROn4DipKaUcjiZRSpyIsW88FMLlqzr3hV_hnahKZZ7QposeAtVRB4Cgd_2dauuJkKQc5RaRFV732XavKLR_GrjVR9a9WTFfPxuUgaktqbGkxS8c4Ak30VHB-85AZww0/s1600/Screen+Shot+2016-08-06+at+9.05.17+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="131" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnxmTMV5NbmHfjROn4DipKaUcjiZRSpyIsW88FMLlqzr3hV_hnahKZZ7QposeAtVRB4Cgd_2dauuJkKQc5RaRFV732XavKLR_GrjVR9a9WTFfPxuUgaktqbGkxS8c4Ak30VHB-85AZww0/s400/Screen+Shot+2016-08-06+at+9.05.17+PM.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Berikutnya adalah membuat menu di SideMenuController. Desain layoutnya dengan UITableView sebagai berikut :&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFJfMiYE4X04yPVnm7W1RRozkbMEP8x2FNtCGXBfABrJ7qpBFXvq7AJzCOgVL-6OopLwTlAmu1VdpeYwpTZurCw1rlmFIXU33vcMVZm7wWjMJgaHNMxtK_3gY_bIQP4oulJu21SyzDWXk/s1600/Screen+Shot+2016-08-06+at+9.06.12+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFJfMiYE4X04yPVnm7W1RRozkbMEP8x2FNtCGXBfABrJ7qpBFXvq7AJzCOgVL-6OopLwTlAmu1VdpeYwpTZurCw1rlmFIXU33vcMVZm7wWjMJgaHNMxtK_3gY_bIQP4oulJu21SyzDWXk/s400/Screen+Shot+2016-08-06+at+9.06.12+PM.png" width="376" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLm2xQkssUxP7nTPPIeU8foD1E1Oe_vyYVHa1J_A0125scIccgf_IrS_NB7OyibjUf9X18cgoetiUppnaW9c57Ch9_jr1dRAIyn2-Qf6Qs4n8_R3-FkUvKObideHQVzsdVBSbrrrTFDdc/s1600/Screen+Shot+2016-08-06+at+9.06.35+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLm2xQkssUxP7nTPPIeU8foD1E1Oe_vyYVHa1J_A0125scIccgf_IrS_NB7OyibjUf9X18cgoetiUppnaW9c57Ch9_jr1dRAIyn2-Qf6Qs4n8_R3-FkUvKObideHQVzsdVBSbrrrTFDdc/s400/Screen+Shot+2016-08-06+at+9.06.35+PM.png" width="206" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Setelah layoutnya selesai, buat kelas-kelas &lt;b&gt;Swift&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
Pertama, buat kelas &lt;b&gt;SideMenuController.swift&lt;/b&gt;, di kelas ini lah kita akan mengatur menunya.&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import Foundation
import UIKit

class SideMenuController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    
    @IBOutlet weak var tableView: UITableView!
    
    let arrayTitle = ["Home", "Profile", "Notifications", "Favorites", "Settings"]
    let arrayIcon = ["ic_home_36pt", "ic_person_36pt", "ic_notifications_36pt", "ic_star_36pt", "ic_settings_36pt"]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        self.tableView.dataSource = self
        self.tableView.delegate = self
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    override func preferredStatusBarStyle() -&amp;gt; UIStatusBarStyle {
        return .LightContent
    }
    
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -&amp;gt; Int {
        return arrayTitle.count
    }
    
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -&amp;gt; UITableViewCell {
        
        let cell: SideBarCell = tableView.dequeueReusableCellWithIdentifier("SideBarCell") as! SideBarCell
        
        cell.title.text = arrayTitle[indexPath.row]
        cell.icon.image = UIImage(named: arrayIcon[indexPath.row])
        
        return cell
    }
    
    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        
        switch (indexPath.row) {
        case 0:
            self.performSegueWithIdentifier("home_segue", sender: self)
            break
        case 1:
            self.performSegueWithIdentifier("profile_segue", sender: self)
            break
        case 2:
            self.performSegueWithIdentifier("notifications_segue", sender: self)
            break
        case 3:
            self.performSegueWithIdentifier("favorites_segue", sender: self)
            break
        case 4:
            self.performSegueWithIdentifier("settings_segue", sender: self)
            break
        default:
            break
        }
    }

}
&lt;/pre&gt;
&lt;b&gt;SideBarCell.swift
&lt;/b&gt;
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import Foundation

class SideBarCell: UITableViewCell {
    
    @IBOutlet weak var icon: UIImageView!
    @IBOutlet weak var title: UILabel!
    
}
&lt;/pre&gt;
&lt;b&gt;HomeViewController.swift&lt;/b&gt;
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import Foundation

class HomeViewController: UIViewController {
    
    @IBOutlet weak var menuBar: UIBarButtonItem!
    
    override func viewDidLoad() {
        setMenuBarBtn(menuBar)
    }
    
    func setMenuBarBtn(menuBar: UIBarButtonItem) {
        menuBar.target = revealViewController()
        menuBar.action = #selector(SWRevealViewController.revealToggle(_:))
        view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
    }
    
    override func preferredStatusBarStyle() -&amp;gt; UIStatusBarStyle {
        return .LightContent
    }
    
    override func supportedInterfaceOrientations() -&amp;gt; UIInterfaceOrientationMask {
        return UIInterfaceOrientationMask.Portrait
    }
}
&lt;/pre&gt;
&lt;b&gt;ProfileViewController.swift
&lt;/b&gt;&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import Foundation

class ProfileViewController: UIViewController {
    
    @IBOutlet weak var menuBar: UIBarButtonItem!
    
    override func viewDidLoad() {
        setMenuBarBtn(menuBar)
    }
    
    func setMenuBarBtn(menuBar: UIBarButtonItem) {
        menuBar.target = revealViewController()
        menuBar.action = #selector(SWRevealViewController.revealToggle(_:))
        view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
    }
    
    override func preferredStatusBarStyle() -&amp;gt; UIStatusBarStyle {
        return .LightContent
    }
    
    override func supportedInterfaceOrientations() -&amp;gt; UIInterfaceOrientationMask {
        return UIInterfaceOrientationMask.Portrait
    }
}
&lt;/pre&gt;
&lt;b&gt;NotificationsViewController.swift
&lt;/b&gt;&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import Foundation

class NotificationsViewController: UIViewController {
    
    @IBOutlet weak var menuBar: UIBarButtonItem!
    
    override func viewDidLoad() {
        setMenuBarBtn(menuBar)
    }
    
    func setMenuBarBtn(menuBar: UIBarButtonItem) {
        menuBar.target = revealViewController()
        menuBar.action = #selector(SWRevealViewController.revealToggle(_:))
        view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
    }
    
    override func preferredStatusBarStyle() -&amp;gt; UIStatusBarStyle {
        return .LightContent
    }
    
    override func supportedInterfaceOrientations() -&amp;gt; UIInterfaceOrientationMask {
        return UIInterfaceOrientationMask.Portrait
    }
}
&lt;/pre&gt;
&lt;b&gt;FavoritesViewController.swift
&lt;/b&gt;&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import Foundation

class FavoritesViewController: UIViewController {
    
    @IBOutlet weak var menuBar: UIBarButtonItem!
    
    override func viewDidLoad() {
        setMenuBarBtn(menuBar)
    }
    
    func setMenuBarBtn(menuBar: UIBarButtonItem) {
        menuBar.target = revealViewController()
        menuBar.action = #selector(SWRevealViewController.revealToggle(_:))
        view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
    }
    
    override func preferredStatusBarStyle() -&amp;gt; UIStatusBarStyle {
        return .LightContent
    }
    
    override func supportedInterfaceOrientations() -&amp;gt; UIInterfaceOrientationMask {
        return UIInterfaceOrientationMask.Portrait
    }
}
&lt;/pre&gt;
&lt;b&gt;SettingsViewController.swift
&lt;/b&gt;&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import Foundation

class SettingsViewController: UIViewController {
    
    @IBOutlet weak var menuBar: UIBarButtonItem!
    
    override func viewDidLoad() {
        setMenuBarBtn(menuBar)
    }
    
    func setMenuBarBtn(menuBar: UIBarButtonItem) {
        menuBar.target = revealViewController()
        menuBar.action = #selector(SWRevealViewController.revealToggle(_:))
        view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
    }
    
    override func preferredStatusBarStyle() -&amp;gt; UIStatusBarStyle {
        return .LightContent
    }
    
    override func supportedInterfaceOrientations() -&amp;gt; UIInterfaceOrientationMask {
        return UIInterfaceOrientationMask.Portrait
    }
}
&lt;/pre&gt;
Selesai, sekarang tinggal build dan running maka hasilnya seperti berikut :&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5q8EDQL2MaMbsbxKVOXYvkCHoVShIdVeo8gcvKL5PDbvC7DndU2xkr43mp590OVe0UoAWT91WGI-7utq3b4-6XIYgvtulkGhFX1PbufwMCAFLHb-JKMys6iesvpcVuDNOI-Rjn5_As4Q/s1600/Simulator+Screen+Shot+Aug+6%252C+2016%252C+8.36.56+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5q8EDQL2MaMbsbxKVOXYvkCHoVShIdVeo8gcvKL5PDbvC7DndU2xkr43mp590OVe0UoAWT91WGI-7utq3b4-6XIYgvtulkGhFX1PbufwMCAFLHb-JKMys6iesvpcVuDNOI-Rjn5_As4Q/s400/Simulator+Screen+Shot+Aug+6%252C+2016%252C+8.36.56+PM.png" width="225" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Source Code lengkap bisa dilihat di sini&amp;nbsp;&lt;a href="https://github.com/wimsonevel/SidebarMenu-Swift"&gt;https://github.com/wimsonevel/SidebarMenu-Swift&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Ok, Sekian tutorial kali ini dan semoga bermanfaat&lt;br /&gt;
Happy Coding ^^</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRLFGlWnOo-onvLUD6nkB2OjWA8R5gHIRCVYVfkwZvu1SEzaNcWLvGWNTEIW3traUQoo-x326R-iQVa0amJYNC9b__AYT_p5SDeXqnugpt-UyzaAdn0LNRDa_UKNkQsmzhSsci-7K6iBE/s72-c/ios+sidebar.png" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>(Tutorial iOS) Tab Menu with Tab Bar Controller</title><link>http://wimsonevel.blogspot.com/2016/07/tutorial-ios-tab-menu-with-tab-bar.html</link><category>iOS</category><category>Swift</category><author>noreply@blogger.com (Wim Sonevel)</author><pubDate>Sat, 30 Jul 2016 19:17:00 +0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-6966757688576433754.post-7784768975787098657</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjl-u36oKWzvVUllQp1tcPuMU2Iy-vuBr5s8qNVb2OckutyAsGlU356EMjeuvvsRp46GIxvLsL7l1dO5Ip56SW826K_40-1OtSJknnMgw0UJ1GCHFNAY6hhT75cjuGBIc6gvsck_LuobwQ/s1600/ios+tab+bar.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="800" data-original-width="1280" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjl-u36oKWzvVUllQp1tcPuMU2Iy-vuBr5s8qNVb2OckutyAsGlU356EMjeuvvsRp46GIxvLsL7l1dO5Ip56SW826K_40-1OtSJknnMgw0UJ1GCHFNAY6hhT75cjuGBIc6gvsck_LuobwQ/s640/ios+tab+bar.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
&lt;br /&gt;
Membuat menu Tab pada apps iOS kita dapat menggunakan Tab Bar Controller. Beberapa view controller dapat direlasikan ke  Tab Bar Controller. Beberapa contoh apps yang menggunakan menu tab.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuJej1xcBXldYNNI4RO6QSST1ciUWxEFRlcVcZ7IvehglaHqZQa15_N-jcZMamZ-HoYDMrI-IRWcaMMWBfy6rhvRPdMy7ED9n-m1twGCW5vptMur98my9wjW6MyGBVZ9Gd3s8K0d9P2g4/s1600/apps_tabs.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuJej1xcBXldYNNI4RO6QSST1ciUWxEFRlcVcZ7IvehglaHqZQa15_N-jcZMamZ-HoYDMrI-IRWcaMMWBfy6rhvRPdMy7ED9n-m1twGCW5vptMur98my9wjW6MyGBVZ9Gd3s8K0d9P2g4/s640/apps_tabs.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Berbeda dengan Android, posisi Tab di iOS berada di bagian bawah layar.&lt;br /&gt;
&lt;br /&gt;
Pada postingan kali ini saya akan membahas bagaimana membuat Tab dengan Tab Bar Controller.&lt;br /&gt;
&lt;br /&gt;
Buat project baru di &lt;b&gt;Xcode&lt;/b&gt;, kemudian buka &lt;b&gt;Main.storyboard&lt;/b&gt;. Desain storyboard nantinya akan seperti ini.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcgJ_WNBKouEOP9gMGHIs0DusJce8Ns7CeQGCaRnBibd5BvP7w0Mk4jhz_SfmDkWZDW7KyLg6hnZpjugfRS2AKAEecAqv0cHMAA2A1JdWm76PW-QKIwmf3vvLIfsQeYrui1hhzWsEaej8/s1600/Screen+Shot+2016-07-30+at+5.44.22+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="462" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcgJ_WNBKouEOP9gMGHIs0DusJce8Ns7CeQGCaRnBibd5BvP7w0Mk4jhz_SfmDkWZDW7KyLg6hnZpjugfRS2AKAEecAqv0cHMAA2A1JdWm76PW-QKIwmf3vvLIfsQeYrui1hhzWsEaej8/s640/Screen+Shot+2016-07-30+at+5.44.22+PM.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Pada storyboard terdiri dari Tab Bar Controller dan 4 buah View Controller yang memiliki relasi dengan Tab Bar Controller.&lt;br /&gt;
&lt;br /&gt;
Drag &amp;amp; drop &lt;b&gt;Tab Bar Controller&lt;/b&gt;, lalu letakkan di storyboard.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjw2jxtvjRGnXxW0mxpkfmi6se_69oPISK-Z2WgXFcaHxPuavgfySB3MuZC6Ikhyphenhyphen64CrQ3ikRYTZKWI7wYiMaHaWIxmXDUNIXRW9OLwNRXyq_MJ-TQlaf96_krV7XDvIrrc_K48o4o_wLw/s1600/Screen+Shot+2016-07-30+at+5.47.29+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjw2jxtvjRGnXxW0mxpkfmi6se_69oPISK-Z2WgXFcaHxPuavgfySB3MuZC6Ikhyphenhyphen64CrQ3ikRYTZKWI7wYiMaHaWIxmXDUNIXRW9OLwNRXyq_MJ-TQlaf96_krV7XDvIrrc_K48o4o_wLw/s1600/Screen+Shot+2016-07-30+at+5.47.29+PM.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Lalu tambahkan 4 &lt;b&gt;View Controller&lt;/b&gt; di storyboard. Control drag dari Tab Bar Controller lalu  pilih &lt;b&gt;Relationship Segue&lt;/b&gt; untuk merelasikan. &lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUiiNxTF6AMzUBaoZKErFemfXbQ4Bwwcsyw5ikugxXNUp8Qi1OkNO40iFqOj4RlloXsTkXPYYzRD-M-uOWBnFRtozrBZNfalpAA1kwGDRH-VaIzP4GeFUaiMdaGsT_bjBJD04RDJ2fpb8/s1600/Screen+Shot+2016-07-30+at+5.49.32+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUiiNxTF6AMzUBaoZKErFemfXbQ4Bwwcsyw5ikugxXNUp8Qi1OkNO40iFqOj4RlloXsTkXPYYzRD-M-uOWBnFRtozrBZNfalpAA1kwGDRH-VaIzP4GeFUaiMdaGsT_bjBJD04RDJ2fpb8/s1600/Screen+Shot+2016-07-30+at+5.49.32+PM.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Pada &lt;b&gt;View Controller&lt;/b&gt; pertama, kita jadikan sebagai &lt;b&gt;Home&lt;/b&gt;. &lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjc5ukAw09rNxK4YWuEnV8Dsr0L1UkR6n6hAKCfong1iyVNd2dyN4uieLtKdAMzUElu0l0ww4PKt1IkMR_OUNd8VZZp9UdIjMpo5geuzqu1gA7NwJ4gnkrgX6MbBvIyby9QhgN5PIOTuMc/s1600/Screen+Shot+2016-07-30+at+5.52.50+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="390" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjc5ukAw09rNxK4YWuEnV8Dsr0L1UkR6n6hAKCfong1iyVNd2dyN4uieLtKdAMzUElu0l0ww4PKt1IkMR_OUNd8VZZp9UdIjMpo5geuzqu1gA7NwJ4gnkrgX6MbBvIyby9QhgN5PIOTuMc/s400/Screen+Shot+2016-07-30+at+5.52.50+PM.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiabqtTMpNS3dolvOum1ydWlAqDZe1MfpRtFoSqkwuMsGKwNEJArwWuyxAxMHMFh0jnSqGrD4NgUMXotZoJXOx0XmYBf0IzV9-svjsh5bx_UMCS3V2KqXbxUyJgVgEx312M-e2V9Y5FO1o/s1600/Screen+Shot+2016-07-30+at+5.53.22+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiabqtTMpNS3dolvOum1ydWlAqDZe1MfpRtFoSqkwuMsGKwNEJArwWuyxAxMHMFh0jnSqGrD4NgUMXotZoJXOx0XmYBf0IzV9-svjsh5bx_UMCS3V2KqXbxUyJgVgEx312M-e2V9Y5FO1o/s1600/Screen+Shot+2016-07-30+at+5.53.22+PM.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Untuk menambahkan icon &amp;amp; mengedit title dapat diatur di &lt;b&gt;Attributes Inspector&lt;/b&gt;.
&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSceYDteTNXttNi8Lyaa1uS16JKWr2kvtEQYEJsk0TlTiJ1yEOZc-YgfG9_v8pR4rmrmd0N53splQi89cc5MRqqgCZifO6SYhJPZOsFRLPC150EqHXnRhd4k_SLXUQ8Lt_-7fboC6cVYI/s1600/Screen+Shot+2016-07-30+at+5.53.11+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSceYDteTNXttNi8Lyaa1uS16JKWr2kvtEQYEJsk0TlTiJ1yEOZc-YgfG9_v8pR4rmrmd0N53splQi89cc5MRqqgCZifO6SYhJPZOsFRLPC150EqHXnRhd4k_SLXUQ8Lt_-7fboC6cVYI/s1600/Screen+Shot+2016-07-30+at+5.53.11+PM.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Lakukan hal yang sama pada 3 buah &lt;b&gt;View Controller&lt;/b&gt; lainnya.&lt;br /&gt;
&lt;br /&gt;
Setelah selesai, coba build dan jalankan maka hasilnya seperti berikut :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAG00DZMh-vnS6iyS-diDp4GVMxLzktyEB7GNACR5FNZaLSDvVrhuoEjT-LA57yH-Bob-fwJi-glhuBcqRCKR4hxLcBQjIgxiGcu5Oc06CId51LylQuwlKrVbbajXALGKPLpnA7Qq2LzM/s1600/Simulator+Screen+Shot+Jul+30%252C+2016%252C+5.59.30+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAG00DZMh-vnS6iyS-diDp4GVMxLzktyEB7GNACR5FNZaLSDvVrhuoEjT-LA57yH-Bob-fwJi-glhuBcqRCKR4hxLcBQjIgxiGcu5Oc06CId51LylQuwlKrVbbajXALGKPLpnA7Qq2LzM/s400/Simulator+Screen+Shot+Jul+30%252C+2016%252C+5.59.30+PM.png" width="225" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Custom Tab Bar&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Kita dapat meng-custom tab seperti warna background tab dan tint icon. Buka file AppDelegate dan tambahkan kode berikut di dalam method application:&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;AppDelegate.swift
&lt;/b&gt;
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;….

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -&amp;gt; Bool {
        // Override point for customization after application launch.
    
        UITabBar.appearance().tintColor = UIColor(red: 244/255, green: 67/255, blue:54/255, alpha: 1.0)
        UITabBar.appearance().barTintColor = UIColor.blackColor()
        return true
    }

….
&lt;/pre&gt;
Build dan jalankan lagi maka hasilnya seperti berikut :&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNVQ7GPcNrIwEhg48gblXiP9051VQFMnB73ylHakrePodGvIfR2Dyr7789S8YQp4hFuUKZc-rdiLGVWshywbe9-GPSjvy28DF6sa-HF6AR5XbImC3lLOFX4opj7Mpu-Wpihqcmy3_pCOY/s1600/Simulator+Screen+Shot+Jul+30%252C+2016%252C+6.56.06+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNVQ7GPcNrIwEhg48gblXiP9051VQFMnB73ylHakrePodGvIfR2Dyr7789S8YQp4hFuUKZc-rdiLGVWshywbe9-GPSjvy28DF6sa-HF6AR5XbImC3lLOFX4opj7Mpu-Wpihqcmy3_pCOY/s400/Simulator+Screen+Shot+Jul+30%252C+2016%252C+6.56.06+PM.png" width="225" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Source code dapat dilihat di&amp;nbsp;&lt;a href="https://github.com/wimsonevel/TabBar-iOS"&gt;https://github.com/wimsonevel/TabBar-iOS&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Sekian tutorial kali ini, semoga bermanfaat.&lt;br /&gt;
Terima Kasih !&lt;br /&gt;
&lt;br /&gt;
Happy Coding :)&lt;br /&gt;
&lt;br /&gt;
More Reference :&amp;nbsp;&lt;a href="https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/UIKitUICatalog/UITabBar.html"&gt;https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/UIKitUICatalog/UITabBar.html&lt;/a&gt;</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjl-u36oKWzvVUllQp1tcPuMU2Iy-vuBr5s8qNVb2OckutyAsGlU356EMjeuvvsRp46GIxvLsL7l1dO5Ip56SW826K_40-1OtSJknnMgw0UJ1GCHFNAY6hhT75cjuGBIc6gvsck_LuobwQ/s72-c/ios+tab+bar.png" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>(Chord Tutorial) OST Digimon Tri – Butterfly</title><link>http://wimsonevel.blogspot.com/2016/07/chord-tutorial-ost-digimon-tri-butterfly.html</link><category>Chord OST Anime</category><author>noreply@blogger.com (Wim Sonevel)</author><pubDate>Mon, 25 Jul 2016 17:55:00 +0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-6966757688576433754.post-4157071133978589999</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinQPMw2rUJw0hhdjFh4SWm31YsmpjH68q6lCv7qu20CAsqyWu_S_TEAJfDrQx5Vb9vuHCOTf5hfnKV91AcqNvAKf98AhRpCKvJIJhdNlVkVbR6GlNkHgi-2DswJqm7CJA93d99d0Own8o/s1600/Digimon+Tri.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinQPMw2rUJw0hhdjFh4SWm31YsmpjH68q6lCv7qu20CAsqyWu_S_TEAJfDrQx5Vb9vuHCOTf5hfnKV91AcqNvAKf98AhRpCKvJIJhdNlVkVbR6GlNkHgi-2DswJqm7CJA93d99d0Own8o/s400/Digimon+Tri.jpg" width="281" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;b&gt;OST Digimon Adventure Tri Version - Butterfly&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;iframe frameborder="no" height="450" scrolling="no" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/234666822&amp;amp;auto_play=false&amp;amp;hide_related=false&amp;amp;show_comments=true&amp;amp;show_user=true&amp;amp;show_reposts=false&amp;amp;visual=true" width="100%"&gt;&lt;/iframe&gt;

Lagu ini merupakan OST Digimon Adventure Tri Version. Karena saya sendiri suka lagunya jadi saya buatin chord tutorialnya bagi yang ingin meng-cover lagunya.&lt;br /&gt;
&lt;br /&gt;
Check it out ! :)&lt;br /&gt;
&lt;br /&gt;
Ab &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Bb &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Cm &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Gm&lt;br /&gt;
Stay shigachi na imeeji darake no tayorinai tsubasa demo&lt;br /&gt;
Ab &amp;nbsp; &amp;nbsp;Eb &amp;nbsp; &amp;nbsp; &amp;nbsp;Cm&lt;br /&gt;
Kitto toberu sa&lt;br /&gt;
B &amp;nbsp; C# &amp;nbsp;Eb&lt;br /&gt;
Oh my love&lt;br /&gt;
&lt;br /&gt;
Intro :&lt;br /&gt;
Eb Ab Eb C#&lt;br /&gt;
&lt;br /&gt;
Ab &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Cm &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Gm&lt;br /&gt;
Gokigen na chou ni natte kirameku kaze ni notte&lt;br /&gt;
Ab &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; B &amp;nbsp; &amp;nbsp; &amp;nbsp;C# &amp;nbsp; Eb&lt;br /&gt;
Ima sugu kimi ni ai ni yukou&lt;br /&gt;
Ab &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Cm &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Gm&lt;br /&gt;
Yokei na koto nante wasureta hou ga mashi sa&lt;br /&gt;
Ab &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;B &amp;nbsp; &amp;nbsp; &amp;nbsp; C# &amp;nbsp; &amp;nbsp; &amp;nbsp; Eb&lt;br /&gt;
Kore ijou shareteru jikan wa nai&lt;br /&gt;
&lt;br /&gt;
Cm &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Gm &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Ab &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Eb&lt;br /&gt;
Nani ga wow wow wow wow~ kono sora ni todoku no darou&lt;br /&gt;
Cm &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Gm &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; C# &amp;nbsp; &amp;nbsp; Eb &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; E &amp;nbsp; F# &amp;nbsp;Eb&lt;br /&gt;
Dakedo wow wow wow wow~ ashita no yotei mo wakaranai&lt;br /&gt;
&lt;br /&gt;
Eb &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Bb &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Cm &amp;nbsp; &amp;nbsp; &amp;nbsp;Gm &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Ab&lt;br /&gt;
Mugendai na yume no ato no nanimo nai yo no naka ja&lt;br /&gt;
Eb &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Cm Ab &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Bb&lt;br /&gt;
Sou sa itoshii omoi mo makesou ni naru kedo&lt;br /&gt;
Eb &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Bb &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Cm &amp;nbsp; &amp;nbsp;Gm &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Ab&lt;br /&gt;
Stay shigachi na imeeji darake no tayorinai tsubasa demo&lt;br /&gt;
Gm &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Cm&lt;br /&gt;
Kitto toberu sa&lt;br /&gt;
B &amp;nbsp; &amp;nbsp;C# Eb&lt;br /&gt;
Oh my love&lt;br /&gt;
&lt;br /&gt;
Eb Ab Eb C#&lt;br /&gt;
&lt;br /&gt;
Ab &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Cm &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Gm&lt;br /&gt;
Ukareta chou ni natte ichizu na kaze ni notte&lt;br /&gt;
Ab &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; B &amp;nbsp; &amp;nbsp; C# &amp;nbsp; &amp;nbsp;Eb&lt;br /&gt;
Doko mademo kimi ni ai ni yukou&lt;br /&gt;
Ab &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Cm &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Gm&lt;br /&gt;
Aimai na kotoba tte igai ni benri datte&lt;br /&gt;
Ab &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;B &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;C# &amp;nbsp; &amp;nbsp; Eb&lt;br /&gt;
Sakenderu hitto songu kikinagara&lt;br /&gt;
&lt;br /&gt;
Cm &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Gm &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Ab &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Eb&lt;br /&gt;
Nani ga wow wow wow wow~ kono machi ni hibiku no darou&lt;br /&gt;
Cm &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Gm &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;C# &amp;nbsp; &amp;nbsp; &amp;nbsp; Eb &amp;nbsp; &amp;nbsp; &amp;nbsp; E &amp;nbsp;F# &amp;nbsp;Eb&lt;br /&gt;
Dakedo wow wow wow wow~ kitai shitetemo shikata nai&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Eb &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Bb &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Cm &amp;nbsp; &amp;nbsp; &amp;nbsp; Gm &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Ab &lt;br /&gt;
Mugendai na yume no ato no yarusenai yo no naka ja&lt;br /&gt;
Eb &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Cm Ab &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Bb&lt;br /&gt;
Sou sa joushiki hazure mo waruku wa nai ka na&lt;br /&gt;
Eb &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Bb &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Cm Gm &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Ab&lt;br /&gt;
Stay shisou na imeeji wo someta gikochinai tsubasa demo&lt;br /&gt;
Gm &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Cm&lt;br /&gt;
Kitto toberu sa&lt;br /&gt;
B &amp;nbsp; C# &amp;nbsp;Eb&lt;br /&gt;
Oh my love&lt;br /&gt;
&lt;br /&gt;
Interlude&lt;br /&gt;
Eb&lt;br /&gt;
Fm Gm Ab F Bb&lt;br /&gt;
&lt;br /&gt;
Eb &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Bb &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Cm &amp;nbsp; &amp;nbsp; &amp;nbsp;Gm &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Ab&lt;br /&gt;
Mugendai no yume no ato no nanimo nai yo no naka ja&lt;br /&gt;
Eb &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Cm Ab &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Bb&lt;br /&gt;
Sou sa itoshii omoi mo makesou ni naru kedo&lt;br /&gt;
Eb &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Bb &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Cm &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Gm &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Ab&lt;br /&gt;
Stay shigachi na imeeji darake no tayorinai tsubasa demo&lt;br /&gt;
Gm &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Cm B C#&lt;br /&gt;
Kitto toberu sa oh yeah&lt;br /&gt;
&lt;br /&gt;
Eb &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Bb &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Cm &amp;nbsp; &amp;nbsp; &amp;nbsp;Gm &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Ab&lt;br /&gt;
Mugendai na yume no ato no yarusenai yo no naka ja&lt;br /&gt;
Eb &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Cm Ab &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Bb&lt;br /&gt;
Sou sa joushiki hazure mo waruku wa nai ka na&lt;br /&gt;
Eb &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Bb &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Cm &amp;nbsp; &amp;nbsp; Gm &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Ab&lt;br /&gt;
Stay shisou na imeeji wo someta gikochinai tsubasa demo&lt;br /&gt;
Gm &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Cm&lt;br /&gt;
Kitto toberu sa&lt;br /&gt;
B &amp;nbsp; C# Ab&lt;br /&gt;
Oh my love&lt;br /&gt;
&lt;br /&gt;
Outro :&lt;br /&gt;
Ab Bb Cm Gm 2x&lt;br /&gt;
&lt;br /&gt;</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinQPMw2rUJw0hhdjFh4SWm31YsmpjH68q6lCv7qu20CAsqyWu_S_TEAJfDrQx5Vb9vuHCOTf5hfnKV91AcqNvAKf98AhRpCKvJIJhdNlVkVbR6GlNkHgi-2DswJqm7CJA93d99d0Own8o/s72-c/Digimon+Tri.jpg" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>Thread</title><link>http://wimsonevel.blogspot.com/2016/07/thread.html</link><category>Java</category><author>noreply@blogger.com (Wim Sonevel)</author><pubDate>Sun, 24 Jul 2016 00:26:00 +0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-6966757688576433754.post-7907881341901981558</guid><description>Thread merupakan sebuah intruksi yang dapat berjalan sendiri. Thread mempunyai siklus dari awal sampai akhir. Pada umumnya, thread digunakan untuk multitasking, networking, ataupun yang melibatkan proses secara konkuren.&lt;br /&gt;
&lt;br /&gt;
Multithreading adalah suatu kemampuan yang memungkinkan beberapa kumpulan instruksi dapat dijalankan secara bersamaan dalam sebuah program. Untuk membuat thread baru yang terpisah dari thread utama, maka harus membuat class baru yang merupakan turunan dari kelas &lt;b&gt;thread&lt;/b&gt; atau mengimplementasikan interface &lt;b&gt;runnable&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Contoh program :&lt;br /&gt;
Buat kelas dengan nama HalloThread.java&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;public class HalloThread extends Thread{
	String s;
	
	public HalloThread(String s) {
		// TODO Auto-generated constructor stub
		this.s = s;
	}
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		for(int i=0;i&amp;lt;10;i++){
			System.out.println(s+" "+i+" : Hallo");
			try {
				sleep(300);
			} catch (Exception e) {
				// TODO: handle exception
			}
		}
	}
}
&lt;/pre&gt;
Buat kelas lagi dengan nama TesHallo.java&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;public class TesHallo {
	public static void main(String[]args){
		HalloThread h1 = new HalloThread("TH 1");
		HalloThread h2 = new HalloThread("TH 2");
		HalloThread h3 = new HalloThread("TH 3");
		h1.start();
		h2.start();
		h3.start();
	}
}
&lt;/pre&gt;
&lt;br /&gt;
Output :&lt;br /&gt;
&lt;br /&gt;
TH 1 0 : Hallo&lt;br /&gt;
TH 3 0 : Hallo&lt;br /&gt;
TH 2 0 : Hallo&lt;br /&gt;
TH 3 1 : Hallo&lt;br /&gt;
TH 1 1 : Hallo&lt;br /&gt;
TH 2 1 : Hallo&lt;br /&gt;
TH 2 2 : Hallo&lt;br /&gt;
TH 3 2 : Hallo&lt;br /&gt;
TH 1 2 : Hallo&lt;br /&gt;
TH 3 3 : Hallo&lt;br /&gt;
TH 1 3 : Hallo&lt;br /&gt;
TH 2 3 : Hallo&lt;br /&gt;
TH 2 4 : Hallo&lt;br /&gt;
TH 3 4 : Hallo&lt;br /&gt;
TH 1 4 : Hallo&lt;br /&gt;
TH 2 5 : Hallo&lt;br /&gt;
TH 3 5 : Hallo&lt;br /&gt;
TH 1 5 : Hallo&lt;br /&gt;
TH 2 6 : Hallo&lt;br /&gt;
TH 1 6 : Hallo&lt;br /&gt;
TH 3 6 : Hallo&lt;br /&gt;
TH 2 7 : Hallo&lt;br /&gt;
TH 3 7 : Hallo&lt;br /&gt;
TH 1 7 : Hallo&lt;br /&gt;
TH 3 8 : Hallo&lt;br /&gt;
TH 1 8 : Hallo&lt;br /&gt;
TH 2 8 : Hallo&lt;br /&gt;
TH 2 9 : Hallo&lt;br /&gt;
TH 3 9 : Hallo&lt;br /&gt;
TH 1 9 : Hallo
</description><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>(Tutorial Android) HTTP Client on Android with Retrofit</title><link>http://wimsonevel.blogspot.com/2016/07/tutorial-android-http-client-on-android.html</link><category>Android</category><author>noreply@blogger.com (Wim Sonevel)</author><pubDate>Fri, 22 Jul 2016 17:55:00 +0700</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-6966757688576433754.post-3413548016837362349</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgq306w81I9nyP5io_zo-XKrS2qO6eBTHSJCd-UzukcC-pNMcQ5y2EMrdhp56SKaHD5zLAJyr4UM96QpaFt91gGaLhrWB4YHio9JVH341tQRcTONMmZtr-KQttEJjyrxcitN3sc7H-2jFQ/s1600/android-retrofit.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgq306w81I9nyP5io_zo-XKrS2qO6eBTHSJCd-UzukcC-pNMcQ5y2EMrdhp56SKaHD5zLAJyr4UM96QpaFt91gGaLhrWB4YHio9JVH341tQRcTONMmZtr-KQttEJjyrxcitN3sc7H-2jFQ/s640/android-retrofit.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;br /&gt;
&lt;span style="background-color: #ffeb3b; color: #616161;"&gt;&lt;b&gt;&lt;i&gt;Artikel ini sudah tidak relevan lagi dikarenakan service dari ibacor.com sudah mati. Jadi saya mengharapkan para pembaca untuk memakluminya jika aplikasi tidak bisa dijalankan. Untuk tutorial yang baru bisa dilihat di sini&amp;nbsp;&lt;a href="http://wimsonevel.blogspot.co.id/2017/07/re-tutorial-android-http-client-on.html"&gt;http://wimsonevel.blogspot.co.id/2017/07/re-tutorial-android-http-client-on.html&lt;/a&gt;&lt;/i&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Retrofit&lt;/b&gt; merupakan library HTTP Client untuk Android dan Java. Library ini sangat populer dan banyak digunakan oleh developer khususnya Android. Retrofit sangat mudah digunakan, simpel, extensibility dan memiliki  performance yang sangat bagus jika dibandingkan dengan library yang lain. Dengan menggunakan Retrofit, kita melakukan request ke REST Webservice dengan mudah dengan berbagai macam method-method yang disediakan. Library Retrofit dikembangkan oleh Square. Saya sendiri suka dengan library ini dan juga sering menggunakannya di setiap project-project yang saya kerjakan. :D
&lt;br /&gt;
&lt;br /&gt;
Pada postingan kali ini saya akan membahas tentang penggunaan library Retrofit di Android.  
&lt;br /&gt;
&lt;br /&gt;
Hal yang perlu disiapkan terlebih dahulu adalah API service. Di sini saya menggunakan layanan &lt;b&gt;Free API&lt;/b&gt; dari &lt;b&gt;ibacor&lt;/b&gt;. Selengkapnya bisa dilihat di sini &lt;a href="http://ibacor.com/api"&gt;http://ibacor.com/api&lt;/a&gt;. API yang akan kita gunakan yaitu &lt;b&gt;Jadwal Bioskop 21&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
Contoh requestnya sebagai berikut :&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;b&gt;Daftar Kota :&lt;/b&gt;
&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;b&gt;GET&lt;/b&gt; &lt;a href="http://ibacor.com/api/jadwal-bioskop?k=...."&gt;http://ibacor.com/api/jadwal-bioskop?k=....&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Parameter :&lt;/b&gt;&lt;br /&gt;
k = API Key yang didapat dari ibacor&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Response&lt;/b&gt; : &lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;{
    "status": "success",
    "data": [
        {
            "id": "32",
            "kota": "AMBON"
        },
        {
            "id": "6",
            "kota": "BALIKPAPAN"
        },
        …..
    ]
}

&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;Semua Jadwal Berdasarkan Id Kota&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;GET&lt;/b&gt; &lt;a href="http://ibacor.com/api/jadwal-bioskop?k=...&amp;amp;id=10"&gt;http://ibacor.com/api/jadwal-bioskop?k=...&amp;amp;id=10&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Parameter :&lt;/b&gt;&lt;br /&gt;
k = API Key yang didapat dari ibacor&lt;br /&gt;
id = ID Kota&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Response&lt;/b&gt; : &lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;{
    "status": "success",
    "kota": "JAKARTA",
    "date": "22\/07\/16",
    "data": [
        {
            "movie": "GHOSTBUSTERS",
            "poster": "http:\/\/image.tmdb.org\/t\/p\/w300\/4qnJ1hsMADxzwnOmnwjZTNp0rKT.jpg",
            "genre": "Action, Comedy, Sci-fi",
            "duration": "116 minute",
            "jadwal": [
                {
                    "bioskop": "ANGGREK XXI",
                    "jam": [
                        "12:15",
                        "14:35",
                        "15:25",
                        "16:55",
                        "19:15",
                        "20:15",
                        "21:35"
                    ],
                    "harga": "Rp.50,000"
                },
                …...
            ]
 …..
        }
    ]
}
&lt;/pre&gt;
&lt;br /&gt;
Kita akan membuat aplikasi untuk mengetahui informasi jadwal bioskop 21 di seluruh kota di Indonesia. 

&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Buat project baru.&lt;/b&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKAu6HSLPwM_WIUMGbHuApAyaxR7NNHAt4FHIk4j66U-GkGvUwLDxewX3BGLs0JMPtEmcj5IiuDvYk866C5Jun9cmZglpHYc5l_mEc07apr3QDJyoRI4O_WNsbL0gkcnoBxJQi1z5fYU8/s1600/Screen+Shot+2016-07-22+at+11.48.09+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKAu6HSLPwM_WIUMGbHuApAyaxR7NNHAt4FHIk4j66U-GkGvUwLDxewX3BGLs0JMPtEmcj5IiuDvYk866C5Jun9cmZglpHYc5l_mEc07apr3QDJyoRI4O_WNsbL0gkcnoBxJQi1z5fYU8/s1600/Screen+Shot+2016-07-22+at+11.48.09+AM.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Pertama, tambahkan library retrofit di gradle. Retrofit yang akan digunakan adalah &lt;b&gt;Retrofit 2&lt;/b&gt;. Latest version bisa dilihat di &lt;a href="http://square.github.io/retrofit/"&gt;http://square.github.io/retrofit/&lt;/a&gt;&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;compile 'com.squareup.retrofit2:retrofit:2.1.0'
&lt;/pre&gt;
Dan tambahkan juga converter gson, karena json hasil request akan langsung di convert ke gson object. &lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;compile 'com.squareup.retrofit2:converter-gson:2.1.0'
&lt;/pre&gt;
Tambahkan juga beberapa library pendukung yang diperlukan selengkapnya seperti ini :&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.3.0'
    compile 'com.android.support:design:23.3.0'

    compile 'com.squareup.retrofit2:retrofit:2.1.0'
    compile 'com.squareup.retrofit2:converter-gson:2.1.0'

    compile 'com.squareup.picasso:picasso:2.5.2'
}
&lt;/pre&gt;
&lt;br /&gt;
Inisialisasi &lt;b&gt;BASE_URL&lt;/b&gt; dan &lt;b&gt;API_KEY&lt;/b&gt; sebagai di g&lt;b&gt;radle.properties
&lt;/b&gt;&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;BASE_URL = "http://ibacor.com"
API_KEY = "YOUR API KEY"
&lt;/pre&gt;
&lt;br /&gt;
Kemudian letakkan configurasi &lt;b&gt;BASE_URL&lt;/b&gt; dan &lt;b&gt;API_KEY&lt;/b&gt; di &lt;b&gt;gradle&lt;/b&gt;.
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;...
defaultConfig {
    applicationId "example.wim.androidretrofit"
    minSdkVersion 15
    targetSdkVersion 23
    versionCode 1
    versionName "1.0"
}

buildTypes.each {
    it.buildConfigField 'String', 'BASE_URL', BASE_URL
    it.buildConfigField 'String', 'API_KEY', API_KEY
}

...
&lt;/pre&gt;
Kita akan mulai menambahkan resource yang diperlukan.&lt;br /&gt;
&lt;br /&gt;
values/colors.xml&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;resources&amp;gt;
    &amp;lt;color name="colorPrimary"&amp;gt;#795548&amp;lt;/color&amp;gt;
    &amp;lt;color name="colorPrimaryDark"&amp;gt;#4E342E&amp;lt;/color&amp;gt;
    &amp;lt;color name="colorAccent"&amp;gt;#FF4081&amp;lt;/color&amp;gt;
    &amp;lt;color name="colorWhite"&amp;gt;#FFFFFF&amp;lt;/color&amp;gt;
    &amp;lt;color name="colorGrey"&amp;gt;#E5E5E5&amp;lt;/color&amp;gt;
&amp;lt;/resources&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
values/string.xml&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;resources&amp;gt;
    &amp;lt;string name="app_name"&amp;gt;Cinema XXI&amp;lt;/string&amp;gt;
    &amp;lt;string name="genre"&amp;gt;Genre : %s&amp;lt;/string&amp;gt;
    &amp;lt;string name="duration"&amp;gt;Duration : %s&amp;lt;/string&amp;gt;
&amp;lt;/resources&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
drawable/bg_rounded.xml&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;
&amp;lt;shape xmlns:android="http://schemas.android.com/apk/res/android"&amp;gt;
    &amp;lt;solid android:color="@color/colorPrimary"/&amp;gt;
    &amp;lt;stroke android:width="1dip" android:color="@color/colorPrimary" /&amp;gt;
    &amp;lt;corners android:radius="3dip"/&amp;gt;
    &amp;lt;padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" /&amp;gt;
&amp;lt;/shape&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
Buat beberapa layout berikut :&lt;br /&gt;
&lt;br /&gt;
activity_main.xml&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="example.wim.androidretrofit.MainActivity"&amp;gt;
    &amp;lt;android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/refresh"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"&amp;gt;
        &amp;lt;android.support.v7.widget.RecyclerView
            android:id="@+id/rv_city"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scrollbars="vertical"/&amp;gt;
    &amp;lt;/android.support.v4.widget.SwipeRefreshLayout&amp;gt;
&amp;lt;/RelativeLayout&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
activity_movie.xml&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"&amp;gt;
    &amp;lt;android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/refresh"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"&amp;gt;
        &amp;lt;android.support.v7.widget.RecyclerView
            android:id="@+id/rv_movie"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scrollbars="vertical"/&amp;gt;
    &amp;lt;/android.support.v4.widget.SwipeRefreshLayout&amp;gt;
&amp;lt;/LinearLayout&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
activity_showtime.xml&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"&amp;gt;
    &amp;lt;android.support.v7.widget.RecyclerView
        android:id="@+id/rv_showtime"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="vertical"/&amp;gt;
&amp;lt;/LinearLayout&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
list_item_city.xml&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:clickable="true"
    android:focusable="true"
    android:background="?android:attr/selectableItemBackground"
    android:padding="16dp"&amp;gt;
    &amp;lt;TextView
        android:id="@+id/city"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:text="Jakarta" /&amp;gt;
&amp;lt;/LinearLayout&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
list_item_movie.xml&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:clickable="true"
    android:focusable="true"
    android:background="?android:attr/selectableItemBackground"
    android:padding="@dimen/margin_8dp"&amp;gt;
    &amp;lt;LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"&amp;gt;
        &amp;lt;ImageView
            android:id="@+id/poster"
            android:layout_width="80dp"
            android:layout_height="100dp"
            android:src="@drawable/star_trek"
            android:scaleType="centerCrop"/&amp;gt;
            &amp;lt;LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:padding="8dp"&amp;gt;
                &amp;lt;TextView
                    android:id="@+id/title"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="STAR TREK BEYOND"
                    android:textSize="17sp"
                    android:textStyle="bold"/&amp;gt;
                &amp;lt;LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="vertical"
                    android:layout_marginTop="8dp"&amp;gt;
                    &amp;lt;TextView
                        android:id="@+id/genre"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="@string/genre"
                        android:textSize="16sp"/&amp;gt;
                    &amp;lt;TextView
                        android:id="@+id/duration"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="@string/duration"
                        android:textSize="16sp"/&amp;gt;
                &amp;lt;/LinearLayout&amp;gt;
            &amp;lt;/LinearLayout&amp;gt;
    &amp;lt;/LinearLayout&amp;gt;
&amp;lt;/LinearLayout&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
list_item_showtime.xml&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="@dimen/margin_8dp"&amp;gt;
    &amp;lt;LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="@dimen/margin_8dp"
        android:background="@color/colorGrey"&amp;gt;
        &amp;lt;TextView
            android:id="@+id/theater"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="ATRIUM XXI"
            android:textSize="17sp"
            android:textStyle="bold"/&amp;gt;
        &amp;lt;example.wim.androidretrofit.util.FlowLayout
            android:id="@+id/lyTime"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="4dp"
            android:orientation="vertical"/&amp;gt;
        &amp;lt;TextView
            android:id="@+id/price"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/margin_8dp"
            android:text="Rp. 30.000"
            android:textSize="16sp"/&amp;gt;
    &amp;lt;/LinearLayout&amp;gt;
&amp;lt;/LinearLayout&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
list_item_time.xml&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_margin="4dp"
    android:orientation="vertical"&amp;gt;
    &amp;lt;TextView
        android:id="@+id/time"
        android:layout_width="64dp"
        android:layout_height="wrap_content"
        android:background="@drawable/bg_rounded"
        android:gravity="center"
        android:padding="4dp"
        android:text="00:00"
        android:textColor="@color/colorWhite"/&amp;gt;
&amp;lt;/LinearLayout&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
Selanjutnya kita akan melakukan deklarasi API dengan Retrofit. &lt;br /&gt;
&lt;br /&gt;
Deklarasi API di Retrofit menggunakan Annotations di dalam  method Interface dan parameter-parameter yang diperlukan untuk melakukan request. Setiap method harus mempunyai HTTP Annotation seperti &lt;b&gt;GET, POST, PUT, DELETE &lt;/b&gt;dan&lt;b&gt; HEAD&lt;/b&gt;. Setiap URL resource ditentukan oleh Annotation.&lt;br /&gt;
&lt;br /&gt;
Contohnya :&lt;br /&gt;
&lt;b&gt;@GET(“users/list”)&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;@POST(“users/new”)&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Selain itu, parameter-parameter di method berupa annotations juga seperti &lt;b&gt;@Query, @Path, @Body&lt;/b&gt; dan &lt;b&gt;@Header&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;@Path&lt;/b&gt; : variabel substitusi untuk endpoint API. &lt;br /&gt;
Contohnya : user id bisa disisipi {id} di URLnya.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;@Query&lt;/b&gt; : menentukan parameter berupa key dan value.&lt;br /&gt;
&lt;b&gt;@Body&lt;/b&gt; : mengirimkan request body berupa object melalui POST.&lt;br /&gt;
&lt;b&gt;@Header &lt;/b&gt;: menentukan header.
&lt;br /&gt;
&lt;br /&gt;
Selanjutnya membuat interface yang berisi method-method tadi. Di method tersebut akan digunakan untuk mengirim request berupa daftar kota dan jadwal bioskop.&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package example.wim.androidretrofit.service;
import example.wim.androidretrofit.model.City;
import example.wim.androidretrofit.model.Movie;

import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Query;

/**
 * Created by Wim on 7/19/16.
 */
public interface ApiInterface {

    @GET("api/jadwal-bioskop")
    Call&amp;lt;City&amp;gt; getCity();

    @GET("api/jadwal-bioskop")
    Call&amp;lt;Movie&amp;gt; getMovie(
            @Query("id") String id);
}

&lt;/pre&gt;
&lt;br /&gt;
Kemudian buat kelas service dengan nama ApiService. Di sini kita akan membuat konfigurasi dari Retrofit.&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package example.wim.androidretrofit.service;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

import example.wim.androidretrofit.BuildConfig;
import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import retrofit2.Callback;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * Created by Wim on 7/19/16.
 */
public class ApiService {

    private ApiInterface apiInterface;

    public ApiService(){
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(BuildConfig.BASE_URL)
                .client(builder())
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        apiInterface = retrofit.create(ApiInterface.class);
    }

    private OkHttpClient builder() {
        OkHttpClient.Builder okHttpClient = new OkHttpClient().newBuilder();
        okHttpClient.connectTimeout(20, TimeUnit.SECONDS);
        okHttpClient.writeTimeout(20, TimeUnit.SECONDS);
        okHttpClient.readTimeout(90, TimeUnit.SECONDS);


        okHttpClient.addInterceptor(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                HttpUrl url = request.url()
                        .newBuilder()
                        .addQueryParameter("k", BuildConfig.API_KEY)
                        .build();

                request = request.newBuilder().url(url).build();
                return chain.proceed(request);
            }
        });

        return okHttpClient.build();
    }

    public void getCityList(Callback callback){
        apiInterface.getCity().enqueue(callback);
    }

    public void getMovieList(String id, Callback callback){
        apiInterface.getMovie(id).enqueue(callback);
    }

}
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
Sampai di sini kita sudah membuat kelas untuk melakukan request ke API. Selanjutnya adalah membuat kelas model berdasarkan data di JSON. Berikut kelas-kelasnya :&lt;br /&gt;
&lt;br /&gt;
City.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package example.wim.androidretrofit.model;

import java.util.List;

/**
 * Created by Wim on 7/19/16.
 */
public class City {

    private String status;
    private String message;
    private List&amp;lt;CityData&amp;gt; data;

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public List&amp;lt;CityData&amp;gt; getData() {
        return data;
    }

    public void setData(List&amp;lt;CityData&amp;gt; data) {
        this.data = data;
    }
}
&lt;/pre&gt;
&lt;br /&gt;
CityData.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package example.wim.androidretrofit.model;
import android.os.Parcel;
import android.os.Parcelable;

/**
 * Created by Wim on 7/19/16.
 */
public class CityData implements Parcelable {

    private String id;
    private String kota;

    public CityData() {
    }

    protected CityData(Parcel in) {
        this.id = in.readString();
        this.kota = in.readString();
    }

    public static final Parcelable.Creator&amp;lt;CityData&amp;gt; CREATOR = new Parcelable.Creator&amp;lt;CityData&amp;gt;() {
        @Override
        public CityData createFromParcel(Parcel source) {
            return new CityData(source);
        }

        @Override
        public CityData[] newArray(int size) {
            return new CityData[size];
        }
    };

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getKota() {
        return kota;
    }

    public void setKota(String kota) {
        this.kota = kota;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(this.id);
        dest.writeString(this.kota);
    }

}&lt;/pre&gt;
&lt;br /&gt;
Movie.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package example.wim.androidretrofit.model;

import java.util.List;

/**
 * Created by Wim on 7/19/16.
 */
public class Movie {

    private String status;
    private String message;
    private String kota;
    private String date;
    private List&amp;lt;MovieData&amp;gt; data;

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public String getKota() {
        return kota;
    }

    public void setKota(String kota) {
        this.kota = kota;
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

    public List&amp;lt;MovieData&amp;gt; getData() {
        return data;
    }

    public void setData(List&amp;lt;MovieData&amp;gt; data) {
        this.data = data;
    }
}

&lt;/pre&gt;
&lt;br /&gt;
MovieData.java&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package example.wim.androidretrofit.model;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by Wim on 7/19/16.
 */

public class MovieData implements Parcelable {

    private String movie;
    private String poster;
    private String genre;
    private String duration;
    private List&amp;lt;Showtime&amp;gt; jadwal;

    public MovieData() {
    }

    protected MovieData(Parcel in) {
        this.movie = in.readString();
        this.poster = in.readString();
        this.genre = in.readString();
        this.duration = in.readString();
        this.jadwal = new ArrayList&amp;lt;Showtime&amp;gt;();
        in.readList(this.jadwal, Showtime.class.getClassLoader());
    }

    public static final Parcelable.Creator&amp;lt;MovieData&amp;gt; CREATOR = new Parcelable.Creator&amp;lt;MovieData&amp;gt;() {
        @Override
        public MovieData createFromParcel(Parcel source) {
            return new MovieData(source);
        }
        @Override
        public MovieData[] newArray(int size) {
            return new MovieData[size];
        }
    };

    public String getMovie() {
        return movie;
    }

    public void setMovie(String movie) {
        this.movie = movie;
    }

    public String getPoster() {
        return poster;
    }

    public void setPoster(String poster) {
        this.poster = poster;
    }

    public String getGenre() {
        return genre;
    }

    public void setGenre(String genre) {
        this.genre = genre;
    }

    public String getDuration() {
        return duration;
    }


    public void setDuration(String duration) {
        this.duration = duration;
    }

    public List&amp;lt;Showtime&amp;gt; getJadwal() {
        return jadwal;
    }

    public void setJadwal(List&amp;lt;Showtime&amp;gt; jadwal) {
        this.jadwal = jadwal;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(this.movie);
        dest.writeString(this.poster);
        dest.writeString(this.genre);
        dest.writeString(this.duration);
        dest.writeList(this.jadwal);
    }
}
&lt;/pre&gt;
&lt;br /&gt;
Showtime.java&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package example.wim.androidretrofit.model;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.List;

/**
 * Created by Wim on 7/19/16.
 */
public class Showtime implements Parcelable {

    private String bioskop;
    private List&amp;lt;String&amp;gt; jam;
    private String harga;

    public Showtime() {
    }

    protected Showtime(Parcel in) {
        this.bioskop = in.readString();
        this.jam = in.createStringArrayList();
        this.harga = in.readString();
    }

    public static final Parcelable.Creator&amp;lt;Showtime&amp;gt; CREATOR = new Parcelable.Creator&amp;lt;Showtime&amp;gt;() {
        @Override
        public Showtime createFromParcel(Parcel source) {
            return new Showtime(source);
        }
        @Override
        public Showtime[] newArray(int size) {
            return new Showtime[size];
        }
    };

    public String getBioskop() {
        return bioskop;
    }

    public void setBioskop(String bioskop) {
        this.bioskop = bioskop;
    }

    public List&amp;lt;String&amp;gt; getJam() {
        return jam;
    }

    public void setJam(List&amp;lt;String&amp;gt; jam) {
        this.jam = jam;
    }

    public String getHarga() {
        return harga;
    }

    public void setHarga(String harga) {
        this.harga = harga;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(this.bioskop);
        dest.writeStringList(this.jam);
        dest.writeString(this.harga);
    }
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
Setelah kelas model dibuat, berikutnya membuat kelas-kelas utility.
&lt;br /&gt;
&lt;br /&gt;
DividerItemDecoration.java&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package example.wim.androidretrofit.util;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;

/**
 * Created by Wim on 7/18/16.
 */
public class DividerItemDecoration extends RecyclerView.ItemDecoration {

    private static final int[] ATTRS = new int[]{
            android.R.attr.listDivider
    };
    public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
    public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
    private Drawable mDivider;
    private int mOrientation;

    public DividerItemDecoration(Context context, int orientation) {
        final TypedArray a = context.obtainStyledAttributes(ATTRS);
        mDivider = a.getDrawable(0);
        a.recycle();
        setOrientation(orientation);
    }

    public void setOrientation(int orientation) {
        if (orientation != HORIZONTAL_LIST &amp;amp;&amp;amp; orientation != VERTICAL_LIST) {
            throw new IllegalArgumentException("invalid orientation");
        }
        mOrientation = orientation;
    }

    @Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        if (mOrientation == VERTICAL_LIST) {
            drawVertical(c, parent);
        } else {
            drawHorizontal(c, parent);
        }
    }

    public void drawVertical(Canvas c, RecyclerView parent) {
        final int left = parent.getPaddingLeft();
        final int right = parent.getWidth() - parent.getPaddingRight();
        final int childCount = parent.getChildCount();
        for (int i = 0; i &amp;lt; childCount; i++) {
            final View child = parent.getChildAt(i);
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int top = child.getBottom() + params.bottomMargin;
            final int bottom = top + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    public void drawHorizontal(Canvas c, RecyclerView parent) {
        final int top = parent.getPaddingTop();
        final int bottom = parent.getHeight() - parent.getPaddingBottom();
        final int childCount = parent.getChildCount();
        for (int i = 0; i &amp;lt; childCount; i++) {
            final View child = parent.getChildAt(i);
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int left = child.getRight() + params.rightMargin;
            final int right = left + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        if (mOrientation == VERTICAL_LIST) {
            outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
        } else {
            outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
        }
    }
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
FlowLayout.java&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package example.wim.androidretrofit.util;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import example.wim.androidretrofit.R;

/**
 * Created by Wim on 7/21/16.
 */
public class FlowLayout extends ViewGroup {

    private int paddingHorizontal;
    private int paddingVertical;

    public FlowLayout(Context context) {
        super(context);
        init();
    }

    public FlowLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public FlowLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        paddingHorizontal = getResources().getDimensionPixelSize(R.dimen.margin_8dp);
        paddingVertical = getResources().getDimensionPixelSize(R.dimen.margin_8dp);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int childLeft = getPaddingLeft();
        int childTop = getPaddingTop();
        int lineHeight = 0;
        // 100 is a dummy number, widthMeasureSpec should always be EXACTLY for FlowLayout
        int myWidth = resolveSize(100, widthMeasureSpec);
        int wantedHeight = 0;
        for (int i = 0; i &amp;lt; getChildCount(); i++) {
            final View child = getChildAt(i);
            if (child.getVisibility() == View.GONE) {
                continue;
            }
            // let the child measure itself
            child.measure(
                    getChildMeasureSpec(widthMeasureSpec, 0, child.getLayoutParams().width),
                    getChildMeasureSpec(heightMeasureSpec, 0, child.getLayoutParams().height));
            int childWidth = child.getMeasuredWidth();
            int childHeight = child.getMeasuredHeight();
            // lineheight is the height of current line, should be the height of the heightest view
            lineHeight = Math.max(childHeight, lineHeight);
            if (childWidth + childLeft + getPaddingRight() &amp;gt; myWidth) {
                // wrap this line
                childLeft = getPaddingLeft();
                childTop += paddingVertical + lineHeight;
                lineHeight = childHeight;
            }
            childLeft += childWidth + paddingHorizontal;
        }
        wantedHeight += childTop + lineHeight + getPaddingBottom();
        setMeasuredDimension(myWidth, resolveSize(wantedHeight, heightMeasureSpec));
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        int childLeft = getPaddingLeft();
        int childTop = getPaddingTop();
        int lineHeight = 0;
        int myWidth = right – left;

        for (int i = 0; i &amp;lt; getChildCount(); i++) {
            final View child = getChildAt(i);
            if (child.getVisibility() == View.GONE) {
                continue;
            }
            int childWidth = child.getMeasuredWidth();
            int childHeight = child.getMeasuredHeight();
            lineHeight = Math.max(childHeight, lineHeight);
            if (childWidth + childLeft + getPaddingRight() &amp;gt; myWidth) {
                childLeft = getPaddingLeft();
                childTop += paddingVertical + lineHeight;
                lineHeight = childHeight;
            }
            child.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
            childLeft += childWidth + paddingHorizontal;
        }
    }
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
Buat beberapa kelas adapter berikut :&lt;br /&gt;
&lt;br /&gt;
CityListAdapter.java&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package example.wim.androidretrofit.adapter;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import example.wim.androidretrofit.R;
import example.wim.androidretrofit.listener.RecyclerViewItemClickListener;
import example.wim.androidretrofit.model.CityData;

/**
 * Created by Wim on 7/21/16.
 */
public class CityListAdapter extends RecyclerView.Adapter&amp;lt;CityListAdapter.CityViewHolder&amp;gt;{

    private List&amp;lt;CityData&amp;gt; cityDataList;
    private Context context;
    private RecyclerViewItemClickListener recyclerViewItemClickListener;

    public CityListAdapter(Context context) {
        this.context = context;
        cityDataList = new ArrayList&amp;lt;&amp;gt;();
    }

    private void add(CityData item) {
        cityDataList.add(item);
        notifyItemInserted(cityDataList.size() - 1);
    }

    public void addAll(List&amp;lt;CityData&amp;gt; cityDataList) {
        for (CityData cityData : cityDataList) {
            add(cityData);
        }
    }

    public void remove(CityData item) {
        int position = cityDataList.indexOf(item);
        if (position &amp;gt; -1) {
            cityDataList.remove(position);
            notifyItemRemoved(position);
        }
    }

    public void clear() {
        while (getItemCount() &amp;gt; 0) {
            remove(getItem(0));
        }
    }

    public CityData getItem(int positon){
        return cityDataList.get(positon);
    }

    @Override
    public CityViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_city, parent, false);
        final CityViewHolder cityViewHolder = new CityViewHolder(view);
        cityViewHolder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int adapterPos = cityViewHolder.getAdapterPosition();
                if (adapterPos != RecyclerView.NO_POSITION) {
                    if (recyclerViewItemClickListener != null) {
                        recyclerViewItemClickListener.onItemClick(adapterPos, cityViewHolder.itemView);
                    }
                }
            }
        });
        return cityViewHolder;
    }

    @Override
    public void onBindViewHolder(CityViewHolder holder, int position) {
        final CityData cityData = cityDataList.get(position);
        holder.city.setText(cityData.getKota());
    }

    @Override
    public int getItemCount() {
        return cityDataList.size();
    }
    public void setRecyclerViewItemClickListener(RecyclerViewItemClickListener recyclerViewItemClickListener) {
        this.recyclerViewItemClickListener = recyclerViewItemClickListener;
    }

    static class CityViewHolder extends RecyclerView.ViewHolder {

        TextView city;

        public CityViewHolder(View itemView) {
            super(itemView);

            city = (TextView) itemView.findViewById(R.id.city);
        }
    }
}
&lt;/pre&gt;
&lt;br /&gt;
MovieListAdapter.java&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package example.wim.androidretrofit.adapter;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
import java.util.List;
import example.wim.androidretrofit.R;
import example.wim.androidretrofit.listener.RecyclerViewItemClickListener;
import example.wim.androidretrofit.model.MovieData;

/**
 * Created by Wim on 7/20/16.
 */
public class MovieListAdapter extends RecyclerView.Adapter&amp;lt;MovieListAdapter.MovieViewHolder&amp;gt; {

    private List&amp;lt;MovieData&amp;gt; movieDataList;
    private Context context;
    private RecyclerViewItemClickListener recyclerViewItemClickListener;

    public MovieListAdapter(Context context) {
        this.context = context;
        movieDataList = new ArrayList&amp;lt;&amp;gt;();
    }

    private void add(MovieData item) {
        movieDataList.add(item);
        notifyItemInserted(movieDataList.size() - 1);
    }

    public void addAll(List&amp;lt;MovieData&amp;gt; movieDataList) {
        for (MovieData movieData : movieDataList) {
            add(movieData);
        }
    }

    public void remove(MovieData item) {
        int position = movieDataList.indexOf(item);
        if (position &amp;gt; -1) {
            movieDataList.remove(position);
            notifyItemRemoved(position);
        }
    }
    public void clear() {
        while (getItemCount() &amp;gt; 0) {
            remove(getItem(0));
        }
    }

    public MovieData getItem(int positon){
        return movieDataList.get(positon);
    }

    @Override
    public MovieViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_movie, parent, false);
        final MovieViewHolder movieViewHolder = new MovieViewHolder(view);
        movieViewHolder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int adapterPos = movieViewHolder.getAdapterPosition();
                if (adapterPos != RecyclerView.NO_POSITION) {
                    if (recyclerViewItemClickListener != null) {
                        recyclerViewItemClickListener.onItemClick(adapterPos, movieViewHolder.itemView);
                    }
                }
            }
        });
        return movieViewHolder;
    }

    @Override
    public void onBindViewHolder(MovieViewHolder holder, int position) {
        final MovieData movieData = movieDataList.get(position);
        Picasso.with(context)
                .load(movieData.getPoster())
                .into(holder.poster);
        holder.title.setText(Html.fromHtml(movieData.getMovie()));
        holder.genre.setText(context.getResources().getString(R.string.genre, movieData.getGenre()));
        holder.duration.setText(context.getResources().getString(R.string.duration, movieData.getDuration()));
    }

    @Override
    public int getItemCount() {
        return movieDataList.size();
    }

    public void setRecyclerViewItemClickListener(RecyclerViewItemClickListener recyclerViewItemClickListener) {
        this.recyclerViewItemClickListener = recyclerViewItemClickListener;
    }

    static class MovieViewHolder extends RecyclerView.ViewHolder {

        ImageView poster;
        TextView title;
        TextView genre;
        TextView duration;

        public MovieViewHolder(View itemView) {
            super(itemView);

            poster = (ImageView) itemView.findViewById(R.id.poster);
            title = (TextView) itemView.findViewById(R.id.title);
            genre = (TextView) itemView.findViewById(R.id.genre);
            duration = (TextView) itemView.findViewById(R.id.duration);
        }
    }
}
&lt;/pre&gt;
&lt;br /&gt;
ShowtimeListAdapter.java&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package example.wim.androidretrofit.adapter;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import example.wim.androidretrofit.R;
import example.wim.androidretrofit.model.Showtime;
import example.wim.androidretrofit.util.FlowLayout;

/**
 * Created by Wim on 7/21/16.
 */
public class ShowtimeListAdapter extends RecyclerView.Adapter&amp;lt;ShowtimeListAdapter.ShowtimeViewHolder&amp;gt;{

    private List&amp;lt;Showtime&amp;gt; showtimeList;
    private Context context;

    public ShowtimeListAdapter(Context context) {
        this.context = context;
        showtimeList = new ArrayList&amp;lt;&amp;gt;();
    }

    private void add(Showtime item) {
        showtimeList.add(item);
        notifyItemInserted(showtimeList.size() - 1);
    }

    public void addAll(List&amp;lt;Showtime&amp;gt; showtimeList) {
        for (Showtime showtime : showtimeList) {
            add(showtime);
        }
    }

    public void remove(Showtime item) {
        int position = showtimeList.indexOf(item);
        if (position &amp;gt; -1) {
            showtimeList.remove(position);
            notifyItemRemoved(position);
        }
    }

    public void clear() {
        while (getItemCount() &amp;gt; 0) {
            remove(getItem(0));
        }
    }

    public Showtime getItem(int positon){
        return showtimeList.get(positon);
    }

    @Override
    public ShowtimeViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_showtime, parent, false);
        return new ShowtimeViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ShowtimeViewHolder holder, int position) {
        final Showtime showtime = showtimeList.get(position);
        holder.theater.setText(showtime.getBioskop());
        for (int i=0; i&amp;lt;showtime.getJam().size(); i++) {
            View view = LayoutInflater.from(context).inflate(R.layout.list_item_time, holder.lyTime, false);
            TextView time = (TextView) view.findViewById(R.id.time);
            time.setText(showtime.getJam().get(i));
            holder.lyTime.addView(view);
        }
        holder.price.setText(showtime.getHarga());
    }

    @Override
    public int getItemCount() {
        return showtimeList.size();
    }

    static class ShowtimeViewHolder extends RecyclerView.ViewHolder {

        TextView theater;
        FlowLayout lyTime;
        TextView price;

        public ShowtimeViewHolder(View itemView) {
            super(itemView);

            theater = (TextView) itemView.findViewById(R.id.theater);
            lyTime = (FlowLayout) itemView.findViewById(R.id.lyTime);
            price = (TextView) itemView.findViewById(R.id.price);
        }
    }
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
Buat interface untuk listener ketika recycler item di klik.&lt;br /&gt;
&lt;br /&gt;
RecyclerItemClickListener.java&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package example.wim.androidretrofit.listener;
import android.view.View;
/**
 * Created by Wim on 7/17/16.
 */
public interface RecyclerViewItemClickListener {
    void onItemClick(int position, View view);
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
Langkah selanjutnya adalah buat activity berikut :&lt;br /&gt;
&lt;br /&gt;
MainActivity.java&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package example.wim.androidretrofit;

import android.os.Handler;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import java.net.SocketTimeoutException;

import example.wim.androidretrofit.adapter.CityListAdapter;
import example.wim.androidretrofit.listener.RecyclerViewItemClickListener;
import example.wim.androidretrofit.model.City;
import example.wim.androidretrofit.service.ApiService;
import example.wim.androidretrofit.util.DividerItemDecoration;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class MainActivity extends AppCompatActivity implements RecyclerViewItemClickListener {

    private RecyclerView rvCity;
    private SwipeRefreshLayout swipeRefreshLayout;

    private LinearLayoutManager linearLayoutManager;
    private CityListAdapter cityListAdapter;

    private ApiService apiService;

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

        rvCity = (RecyclerView) findViewById(R.id.rv_city);
        swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.refresh);

        linearLayoutManager = new LinearLayoutManager(this);
        cityListAdapter = new CityListAdapter(this);
        cityListAdapter.setRecyclerViewItemClickListener(this);

        rvCity.setLayoutManager(linearLayoutManager);
        rvCity.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.VERTICAL));
        rvCity.setAdapter(cityListAdapter);

        swipeRefreshLayout.setColorSchemeResources(R.color.colorPrimary);
        swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                refreshData();
            }
        });

        loadData();
    }

    private void loadData(){
        if (swipeRefreshLayout != null)
            swipeRefreshLayout.post(new Runnable() {
                @Override
                public void run() {
                    swipeRefreshLayout.setRefreshing(true);
                }
            });

        apiService = new ApiService();
        apiService.getCityList(new Callback() {
            @Override
            public void onResponse(Call call, Response response) {
                City city = (City) response.body();

                if(city != null) {
                    if(city.getStatus().equals("success")) {
                        cityListAdapter.addAll(city.getData());
                    }else{
                        Toast.makeText(MainActivity.this, city.getMessage(), Toast.LENGTH_LONG).show();
                    }
                    Log.i("STATUS", city.getStatus());
                }else{
                    Toast.makeText(MainActivity.this, "No Data!", Toast.LENGTH_LONG).show();
                }

                if (swipeRefreshLayout != null)
                    swipeRefreshLayout.setRefreshing(false);
            }

            @Override
            public void onFailure(Call call, Throwable t) {
                if(t instanceof SocketTimeoutException) {
                    Toast.makeText(MainActivity.this, "Request Timeout. Please try again!", Toast.LENGTH_LONG).show();
                }else{
                    Toast.makeText(MainActivity.this, "Connection Error!", Toast.LENGTH_LONG).show();
                }
                Log.i("FAILURE", t.toString());

                if (swipeRefreshLayout != null)
                    swipeRefreshLayout.setRefreshing(false);
            }
        });
    }

    private void refreshData(){
        new Handler().post(new Runnable() {
            @Override
            public void run() {
                cityListAdapter.clear();
                loadData();
            }
        });
    }

    @Override
    public void onItemClick(int position, View view) {
        MovieActivity.start(this, cityListAdapter.getItem(position));
    }
}

&lt;/pre&gt;
&lt;br /&gt;
MovieActivity.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;package example.wim.androidretrofit;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;

import java.net.SocketTimeoutException;

import example.wim.androidretrofit.adapter.MovieListAdapter;
import example.wim.androidretrofit.listener.RecyclerViewItemClickListener;
import example.wim.androidretrofit.model.CityData;
import example.wim.androidretrofit.model.Movie;
import example.wim.androidretrofit.service.ApiService;
import example.wim.androidretrofit.util.DividerItemDecoration;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

/**
 * Created by Wim on 7/20/16.
 */
public class MovieActivity extends AppCompatActivity implements RecyclerViewItemClickListener {

    private RecyclerView rvMovie;
    private SwipeRefreshLayout swipeRefreshLayout;

    private LinearLayoutManager linearLayoutManager;
    private MovieListAdapter movieListAdapter;

    private ApiService apiService;
    private CityData cityData;
    private Movie movie;

    public static void start(Context context, CityData cityData) {
        Intent intent = new Intent(context, MovieActivity.class);
        intent.putExtra(MovieActivity.class.getSimpleName(), cityData);
        context.startActivity(intent);
    }

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

        cityData = getIntent().getParcelableExtra(MovieActivity.class.getSimpleName());

        ActionBar actionBar = getSupportActionBar();
        actionBar.setTitle(cityData.getKota());
        actionBar.setDisplayHomeAsUpEnabled(true);

        rvMovie = (RecyclerView) findViewById(R.id.rv_movie);
        swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.refresh);

        linearLayoutManager = new LinearLayoutManager(this);
        movieListAdapter = new MovieListAdapter(this);
        movieListAdapter.setRecyclerViewItemClickListener(this);

        rvMovie.setLayoutManager(linearLayoutManager);
        rvMovie.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.VERTICAL));
        rvMovie.setAdapter(movieListAdapter);

        swipeRefreshLayout.setColorSchemeResources(R.color.colorPrimary);
        swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                refreshData();
            }
        });

        loadData(cityData.getId());
    }

    private void loadData(String id){
        if (swipeRefreshLayout != null)
            swipeRefreshLayout.post(new Runnable() {
                @Override
                public void run() {
                    swipeRefreshLayout.setRefreshing(true);
                }
            });


        apiService = new ApiService();
        apiService.getMovieList(id, new Callback() {
            @Override
            public void onResponse(Call call, Response response) {
                movie = (Movie) response.body();

                if(movie != null){
                    if(movie.getStatus().equals("success")) {
                        movieListAdapter.addAll(movie.getData());
                    }else{
                        Toast.makeText(MovieActivity.this, movie.getMessage(), Toast.LENGTH_LONG).show();
                    }
                    Log.i("STATUS", movie.getStatus());
                }else{
                    Toast.makeText(MovieActivity.this, "No Data!", Toast.LENGTH_LONG).show();
                }

                if (swipeRefreshLayout != null)
                    swipeRefreshLayout.setRefreshing(false);
            }

            @Override
            public void onFailure(Call call, Throwable t) {
                if(t instanceof SocketTimeoutException) {
                    Toast.makeText(MovieActivity.this, "Request Timeout. Please try again!", Toast.LENGTH_LONG).show();
                }else{
                    Toast.makeText(MovieActivity.this, "Connection Error!", Toast.LENGTH_LONG).show();
                }

                Log.i("FAILURE", t.toString());

                if (swipeRefreshLayout != null)
                    swipeRefreshLayout.setRefreshing(false);
            }
        });
    }

    private void refreshData(){
        new Handler().post(new Runnable() {
            @Override
            public void run() {
                movieListAdapter.clear();
                loadData(cityData.getId());
            }
        });
    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();
        finish();
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                finish();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    @Override
    public void onItemClick(int position, View view) {
        ShowtimeActivity.start(this, movieListAdapter.getItem(position), movie.getDate());
    }
}

&lt;/pre&gt;
ShowtimeActivity.java
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.Html;
import android.view.MenuItem;

import example.wim.androidretrofit.adapter.ShowtimeListAdapter;
import example.wim.androidretrofit.model.MovieData;

/**
 * Created by Wim on 7/21/16.
 */
public class ShowtimeActivity extends AppCompatActivity {

    private RecyclerView rvShowtime;

    private LinearLayoutManager linearLayoutManager;
    private ShowtimeListAdapter showtimeListAdapter;

    private MovieData movieData;
    private String date;

    public static void start(Context context, MovieData movieData, String date) {
        Intent intent = new Intent(context, ShowtimeActivity.class);
        intent.putExtra(ShowtimeActivity.class.getSimpleName() + ".movie", movieData);
        intent.putExtra(ShowtimeActivity.class.getSimpleName() + ".date", date);
        context.startActivity(intent);
    }

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

        movieData = getIntent().getParcelableExtra(ShowtimeActivity.class.getSimpleName() + ".movie");
        date = getIntent().getStringExtra(ShowtimeActivity.class.getSimpleName() + ".date");

        ActionBar actionBar = getSupportActionBar();
        actionBar.setTitle(Html.fromHtml(movieData.getMovie()));
        actionBar.setSubtitle(date);
        actionBar.setDisplayHomeAsUpEnabled(true);

        rvShowtime = (RecyclerView) findViewById(R.id.rv_showtime);

        linearLayoutManager = new LinearLayoutManager(this);
        showtimeListAdapter = new ShowtimeListAdapter(this);

        rvShowtime.setLayoutManager(linearLayoutManager);
        rvShowtime.setAdapter(showtimeListAdapter);

        showtimeListAdapter.addAll(movieData.getJadwal());
    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();
        finish();
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                finish();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }
}
&lt;/pre&gt;
Langkah terakhir jangan lupa tambahkan permission di AndroidManifest.xml
&lt;br /&gt;
&lt;pre style="background-color: whitesmoke; color: #616161;"&gt;&amp;lt;uses-permission android:name="android.permission.INTERNET"/&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
Finally, aplikasi kita sudah jadi sekarang tinggal di build dan running. Berikut screenshotnya :&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjW2LHNKcxCQo3PI020OdqgTzbhhTWp6jJ1hyhxSQPpVlD0vh2EBuojhhYBy8cEHSsAygDnmTjZi7YaNy5excwVDbk-0z-DGB23rn7VOQiELJz3zXZiywfPBtYiDaK0Adyv0rRUFYFjflE/s1600/device-2016-07-22-145920.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjW2LHNKcxCQo3PI020OdqgTzbhhTWp6jJ1hyhxSQPpVlD0vh2EBuojhhYBy8cEHSsAygDnmTjZi7YaNy5excwVDbk-0z-DGB23rn7VOQiELJz3zXZiywfPBtYiDaK0Adyv0rRUFYFjflE/s400/device-2016-07-22-145920.png" width="225" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGa8ZX-eaHF6L2Q1s8YJqOcQIP7Rj2TsqpRyFPuxmJnEpHx8Q-32hyphenhyphenI4Uk540pEaq6vqnD8ZAfF2xx3L05b3L4cdVbr4Z8BvaJA1bwe8qLTngU3iZ5Dk4pfLgsSwRQvMBxgdhecU087RU/s1600/device-2016-07-26-160433.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGa8ZX-eaHF6L2Q1s8YJqOcQIP7Rj2TsqpRyFPuxmJnEpHx8Q-32hyphenhyphenI4Uk540pEaq6vqnD8ZAfF2xx3L05b3L4cdVbr4Z8BvaJA1bwe8qLTngU3iZ5Dk4pfLgsSwRQvMBxgdhecU087RU/s400/device-2016-07-26-160433.png" width="225" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZTVVXt6cMML6F5KvNAQgyAFQdDSA0lg0BzVxq0-2c5wCoZwpFIKsCzqEVfoASDr0hxkv4d8w16jrcOMMREp7aZ2RNYelcuUpaJFTe53vNKwxnwu4p2H-tNcC36Wlq6Q5AwVdpwR8aMLI/s1600/device-2016-07-26-160729.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZTVVXt6cMML6F5KvNAQgyAFQdDSA0lg0BzVxq0-2c5wCoZwpFIKsCzqEVfoASDr0hxkv4d8w16jrcOMMREp7aZ2RNYelcuUpaJFTe53vNKwxnwu4p2H-tNcC36Wlq6Q5AwVdpwR8aMLI/s400/device-2016-07-26-160729.png" width="225" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Source code lengkap dapat dilihat di&amp;nbsp;&lt;a href="https://github.com/wimsonevel/Android-JadwalBioskop21"&gt;https://github.com/wimsonevel/Android-JadwalBioskop21&lt;/a&gt;&lt;br /&gt;
Sekian tutorial dari saya, semoga bermanfaat. :)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4TVVNQBS-QbrouBrMu42j0PHGo5y_q00uHIl4lvLEKjK2mm32wA51dzv9DVawK3kx2FTAvzyICBG5Rh2f460bsRdjTvDUd1I-14U2fssot5GI6c1eU3HUEKrgDyJcCxHIHfpbBwRRCtY/s1600/10172759_1505122279701455_6961045153558971762_n.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4TVVNQBS-QbrouBrMu42j0PHGo5y_q00uHIl4lvLEKjK2mm32wA51dzv9DVawK3kx2FTAvzyICBG5Rh2f460bsRdjTvDUd1I-14U2fssot5GI6c1eU3HUEKrgDyJcCxHIHfpbBwRRCtY/s320/10172759_1505122279701455_6961045153558971762_n.jpg" width="213" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
*Arigatou*&lt;/div&gt;
</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgq306w81I9nyP5io_zo-XKrS2qO6eBTHSJCd-UzukcC-pNMcQ5y2EMrdhp56SKaHD5zLAJyr4UM96QpaFt91gGaLhrWB4YHio9JVH341tQRcTONMmZtr-KQttEJjyrxcitN3sc7H-2jFQ/s72-c/android-retrofit.png" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">34</thr:total></item></channel></rss>