<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[ARROW Technologies Blog]]></title><description><![CDATA[Trang tổng hợp các kiến thức về lập trình]]></description><link>https://blog.arrow-tech.vn/</link><image><url>https://blog.arrow-tech.vn/favicon.png</url><title>ARROW Technologies Blog</title><link>https://blog.arrow-tech.vn/</link></image><generator>Ghost 5.81</generator><lastBuildDate>Thu, 09 Apr 2026 14:13:16 GMT</lastBuildDate><atom:link href="https://blog.arrow-tech.vn/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Hướng dẫn crawl website với Scrapy]]></title><description><![CDATA[Crawl
]]></description><link>https://blog.arrow-tech.vn/huong-dan-crawl-website-voi-scrapy-2/</link><guid isPermaLink="false">63915acd7a2f410001205def</guid><dc:creator><![CDATA[Quang Dang]]></dc:creator><pubDate>Tue, 11 Feb 2020 04:42:52 GMT</pubDate><media:content url="https://blog.arrow-tech.vn/content/images/2020/02/maxresdefault.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.arrow-tech.vn/content/images/2020/02/maxresdefault.jpg" alt="H&#x1B0;&#x1EDB;ng d&#x1EAB;n crawl website v&#x1EDB;i Scrapy"><p><a href="https://scrapy.org/?ref=blog.arrow-tech.vn">Scrapy</a> l&#xE0; m&#x1ED9;t tr&#xEC;nh thu th&#x1EAD;p d&#x1EEF; li&#x1EC7;u d&#x1EF1;a tr&#xEA;n Python c&#xF3; th&#x1EC3; &#x111;&#x1B0;&#x1EE3;c s&#x1EED; d&#x1EE5;ng &#x111;&#x1EC3; tr&#xED;ch xu&#x1EA5;t th&#xF4;ng tin t&#x1EEB; c&#xE1;c trang web. N&#xF3; nhanh v&#xE0; &#x111;&#x1A1;n gi&#x1EA3;n, v&#xE0; c&#xF3; th&#x1EC3; &#x111;i&#x1EC1;u h&#x1B0;&#x1EDB;ng c&#xE1;c trang gi&#x1ED1;ng nh&#x1B0; tr&#xEC;nh duy&#x1EC7;t c&#xF3; th&#x1EC3;. N&#xF3; l&#xE0; m&#x1ED9;t trong nh&#x1EEF;ng framework &#xA0;m&#xE3; ngu&#x1ED3;n m&#x1EDF; t&#x1ED1;t nh&#x1EA5;t d&#xF9;ng &#x111;&#x1EC3; crawl d&#x1EEF; li&#x1EC7;u. (<a href="https://www.scrapehero.com/open-source-web-scraping-frameworks-and-tools/?ref=blog.arrow-tech.vn">link</a>)</p><h2 id="b-c-1-c-i-t">B&#x1B0;&#x1EDB;c 1: C&#xE0;i &#x111;&#x1EB7;t </h2><p>&#x1EDE; &#x111;&#xE2;y ch&#xFA;ng t&#xF4;i s&#x1EED; d&#x1EE5;ng <a href="https://virtualenv.pypa.io/en/stable/?ref=blog.arrow-tech.vn" rel="nofollow">virtualenv</a> &#x111;&#x1EC3; c&#xE0;i &#x111;&#x1EB7;t scrapy. &#x110;i&#x1EC1;u n&#xE0;y cho ph&#xE9;p ch&#xFA;ng t&#xF4;i c&#xE0;i &#x111;&#x1EB7;t scrapy m&#xE0; kh&#xF4;ng &#x1EA3;nh h&#x1B0;&#x1EDF;ng &#x111;&#x1EBF;n c&#xE1;c m&#xF4;-&#x111;un c&#xE0;i &#x111;&#x1EB7;t h&#x1EC7; th&#x1ED1;ng kh&#xE1;c.</p><p>T&#x1EA1;o m&#x1ED9;t th&#x1B0; m&#x1EE5;c ch&#x1EE9;a project crawler d&#x1EEF; li&#x1EC7;u d&#xF9;ng &#x111;&#x1EC3; l&#x1B0;u tr&#x1EEF; code v&#xE0; t&#x1EA1;o m&#x1ED9;t m&#xF4;i tr&#x1B0;&#x1EDD;ng &#x1EA3;o trong &#x111;&#xF3;.</p><pre><code>mkdir crawlBlogArrow
cd crawlBlogArrow
virtualenv venv
. venv/bin/activate</code></pre><p>C&#xE0;i &#x111;&#x1EB7;t scrapy</p><pre><code>pip install scrapy</code></pre><p>Ki&#x1EC3;m tra xem n&#xF3; &#x111;&#xE3; ho&#x1EA1;t &#x111;&#x1ED9;ng hay ch&#x1B0;a. M&#xE0;n h&#xEC;nh d&#x1B0;&#x1EDB;i &#x111;&#xE2;y cho th&#x1EA5;y phi&#xEA;n b&#x1EA3;n m&#xE0; t&#xF4;i &#x111;ang s&#x1EED; d&#x1EE5;ng l&#xE0; 1.8.0</p><figure class="kg-card kg-image-card"><img src="https://blog.arrow-tech.vn/content/images/2020/02/1.png" class="kg-image" alt="H&#x1B0;&#x1EDB;ng d&#x1EAB;n crawl website v&#x1EDB;i Scrapy" loading="lazy"></figure><h2 id="b-c-2-t-o-project-v-s-d-ng">B&#x1B0;&#x1EDB;c 2: T&#x1EA1;o Project v&#xE0; s&#x1EED; d&#x1EE5;ng</h2><h3 id="2-1-t-o-project">2.1 T&#x1EA1;o Project </h3><p>&#x110;&#x1EC3; t&#x1EA1;o 1 project scrapy ta s&#x1EED; d&#x1EE5;ng c&#xE2;u l&#x1EC7;nh sau</p><pre><code>scrapy startproject crawl</code></pre><p>&#x110;&#xE2;y l&#xE0; c&#x1EA5;u tr&#xFA;c th&#x1B0; m&#x1EE5;c ch&#xFA;ng ta v&#x1EEB;a t&#x1EA1;o th&#xF4;ng qua Scrapy</p><p>crawl/<br>&#x251C;&#x2500;&#x2500; crawl &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; # n&#x1A1;i ch&#x1EE9;a code c&#x1EE7;a d&#x1EF1; &#xE1;n<br>&#x2502; &#xA0; &#x251C;&#x2500;&#x2500; <strong>init</strong>.py<br>&#x2502; &#xA0; &#x251C;&#x2500;&#x2500; items.py &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0;# n&#x1A1;i &#x111;&#x1ECB;nh ngh&#x129;a c&#xE1;c tr&#x1B0;&#x1EDD;ng d&#x1EEF; li&#x1EC7;u c&#x1EA7;n l&#x1B0;u v&#xE0;o db<br>&#x2502; &#xA0; &#x251C;&#x2500;&#x2500; pipelines.py &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0;# n&#x1A1;i x&#x1EED; l&#xFD; c&#xE1;c item tr&#xED;ch xu&#x1EA5;t &#x111;&#x1B0;&#x1EE3;c v&#xE0; l&#x1B0;u v&#xE0;o db<br>&#x2502; &#xA0; &#x251C;&#x2500;&#x2500; settings.py &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0;# c&#x1EA5;u h&#xEC;nh th&#xEA;m c&#xE1;c ph&#x1EA7;n m&#x1EDF; r&#x1ED9;ng (middlewares) v&#xE0; c&#xE1;c th&#xF4;ng s&#x1ED1; c&#x1EA5;u h&#xEC;nh kh&#xE1;c<br>&#x2502; &#xA0; &#x2514;&#x2500;&#x2500; spiders &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; # th&#x1B0; m&#x1EE5;c ch&#x1EE9;a c&#xE1;c spider<br>&#x2502; &#xA0; &#xA0; &#xA0; &#x2514;&#x2500;&#x2500; <strong>init</strong>.py<br>&#x2514;&#x2500;&#x2500; scrapy.cfg &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0;# file c&#x1EA5;u h&#xEC;nh v&#x1EC1; deploy v&#xE0; settings c&#x1EE7;a project</p><h3 id="2-2-c-t-d-li-u">2.2 &#x110;&#x1EB7;c t&#x1EA3; d&#x1EEF; li&#x1EC7;u</h3><p>File <code>items.py</code> &#x111;&#x1B0;&#x1EE3;c s&#x1EED; d&#x1EE5;ng &#x111;&#x1EC3; khai b&#xE1;o metadata cho nh&#x1EEF;ng d&#x1EEF; li&#x1EC7;u m&#xE0; ch&#xFA;ng ta mu&#x1ED1;n scrape. Trong file n&#xE0;y c&#xF3; class <code>StackItem</code> l&#xE0; class &#x111;&#x1B0;&#x1EE3;c k&#x1EBF; th&#x1EEB;a t&#x1EEB; class <a href="http://doc.scrapy.org/en/latest/topics/items.html?ref=blog.arrow-tech.vn"><code>Item</code></a> c&#x1EE7;a Scrapy. Trong class n&#xE0;y &#x111;&#xE3; &#x111;&#x1ECB;nh ngh&#x129;a tr&#x1B0;&#x1EDB;c m&#x1ED9;t s&#x1ED1; &#x111;&#x1ED1;i t&#x1B0;&#x1EE3;ng m&#xE0; Scrapy c&#x1EA7;n d&#xF9;ng &#x111;&#x1EC3; scrape.</p><pre><code>import scrapy

class StackItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    pass</code></pre><p>B&#xE2;y gi&#x1EDD;, ch&#xFA;ng ta s&#x1EBD; th&#xEA;m v&#xE0; nh&#x1EEF;ng d&#x1EEF; li&#x1EC7;u m&#xE0; ch&#xFA;ng ta c&#x1EA7;n</p><pre><code>import scrapy

class StackItem(scrapy.Item):
    title = scrapy.Field()
    thumb = scrapy.Field()    
    content = scrapy.Field()    
    author = scrapy.Field()</code></pre><h3 id="2-3-t-o-spiders">2.3 T&#x1EA1;o spiders</h3><p>Ch&#xFA;ng ta s&#x1EBD; t&#x1EA1;o m&#x1ED9;t &#xA0;spider <code>blogarrow.py</code> trong th&#x1B0; m&#x1EE5;c <code>spiders</code> &#xA0;&#x111;&#xE3; &#x111;&#x1B0;&#x1EE3;c t&#x1EA1;o &#x1EDF; tr&#xEA;n. Th&#x1B0; m&#x1EE5;c n&#xE0;y kh&#xE1; &#x111;&#x1EB7;c bi&#x1EC7;t, b&#x1EDF;i n&#xF3; l&#xE0; n&#x1A1;i ch&#xFA;ng ta &#x111;&#x1B0;a ra c&#xE1;c ch&#x1EC9; &#x111;&#x1ECB;nh cho Scrapy bi&#x1EBF;t ch&#xED;nh x&#xE1;c ch&#xFA;ng ta mu&#x1ED1;n thu th&#x1EAD;p d&#x1EEF; li&#x1EC7;u g&#xEC;. Trong th&#x1B0; m&#x1EE5;c n&#xE0;y, b&#x1EA1;n c&#xF3; th&#x1EC3; &#x111;&#x1ECB;nh ngh&#x129;a c&#xE1;c Spider kh&#xE1;c nhau cho c&#xE1;c trang Web kh&#xE1;c nhau.</p><p>B&#x1EAF;t &#x111;&#x1EA7;u b&#x1EB1;ng m&#x1ED9;t class k&#x1EBF; th&#x1EEB;a t&#x1EEB; class <code>Spider</code> c&#x1EE7;a Scrapy v&#xE0; ch&#xFA;ng ta s&#x1EBD; th&#xEA;m v&#xE0;o c&#xE1;c thu&#x1ED9;c t&#xED;nh c&#x1EA7;n thi&#x1EBF;t.</p><pre><code>from scrapy import Spider

class CrawlerSpider(Spider):
    name = &quot;crawler&quot;
    allowed_domains = [&quot;blog.arrow-tech.vn&quot;]
    start_urls = [
        &quot;https://blog.arrow-tech.vn/detect-labels-faces-and-landmarks-in-images-with-the-cloud-vision-api/&quot;,
    ]</code></pre><p>Nh&#x1EEF;ng thu&#x1ED9;c t&#xED;nh &#x1EDF; &#x111;&#xE2;y kh&#xE1; d&#x1EC5; hi&#x1EC3;u, ch&#xFA;ng th&#x1EC3; hi&#x1EC7;n &#xFD; ngh&#x129;a qua ch&#xED;nh t&#xEA;n c&#x1EE7;a m&#xEC;nh. N&#x1EBF;u c&#x1EA7;n th&#xEA;m th&#xF4;ng tin, b&#x1EA1;n c&#xF3; th&#x1EC3; tham kh&#x1EA3;o &#x1EDF; <a href="http://doc.scrapy.org/en/latest/topics/spiders.html?ref=blog.arrow-tech.vn">&#x111;&#xE2;y</a>:</p><ul><li><code>name</code> &#x111;&#x1ECB;nh ngh&#x129;a t&#xEA;n c&#x1EE7;a Spider.</li><li><code>allowed_domains</code> ch&#x1EE9;a URL g&#x1ED1;c c&#x1EE7;a trang Web b&#x1EA1;n mu&#x1ED1;n scrape.</li><li><code>start_urls</code> l&#xE0; danh s&#xE1;ch c&#xE1;c URL &#x111;&#x1EC3; Spider b&#x1EAF;t &#x111;&#x1EA7;u qu&#xE1; tr&#xEC;nh scraping. T&#x1EA5;t c&#x1EA3; m&#x1ECD;i d&#x1EEF; li&#x1EC7;u s&#x1EBD; &#x111;&#x1B0;&#x1EE3;c Spider download t&#x1EEB; c&#xE1;c URL &#x1EDF; trong <code>start_urls</code> n&#xE0;y.</li></ul><h3 id="xpath-selector">XPath selector</h3><p>M&#x1ED9;t &#x111;i&#x1EC1;u r&#x1EA5;t quan tr&#x1ECD;ng, &#x111;&#xF3; l&#xE0; <a href="http://doc.scrapy.org/en/latest/topics/selectors.html?ref=blog.arrow-tech.vn">Scrapy s&#x1EED; d&#x1EE5;ng XPath selector</a> &#x111;&#x1EC3; tr&#xED;ch xu&#x1EA5;t d&#x1EEF; li&#x1EC7;u t&#x1EEB; c&#xE1;c trang Web. N&#xF3;i m&#x1ED9;t c&#xE1;ch kh&#xE1;c, &#x111;&#xF3; l&#xE0; ch&#xFA;ng ta c&#xF3; th&#x1EC3; ch&#x1ECD;n l&#x1ECD;c ra m&#x1ED9;t th&#xE0;nh ph&#x1EA7;n ch&#xED;nh x&#xE1;c tr&#xEA;n m&#x1ED9;t trang Web b&#x1EB1;ng c&#xE1;ch s&#x1EED; d&#x1EE5;ng <a href="http://www.w3.org/TR/xpath/?ref=blog.arrow-tech.vn">XPath</a>.</p><h3 id="tr-ch-xu-t-d-li-u">Tr&#xED;ch xu&#x1EA5;t d&#x1EEF; li&#x1EC7;u</h3><p>Ch&#xFA;ng ta th&#x1EF1;c hi&#x1EC7;n tr&#xED;ch xu&#x1EA5;t d&#x1EEF; li&#x1EC7;u v&#x1EDB;i &#x111;o&#x1EA1;n code d&#x1B0;&#x1EDB;i &#x111;&#xE2;y</p><pre><code>import scrapy
from scrapy import Spider
from crawl.items import CrawlItem

class CrawlerSpider(Spider):
    name = &quot;crawler&quot;
    allowed_domains = [&quot;blog.arrow-tech.vn&quot;]
    start_urls = [
        &quot;https://blog.arrow-tech.vn/detect-labels-faces-and-landmarks-in-images-with-the-cloud-vision-api/&quot;,
    ]
    
    def parse(self, response):

        item = CrawlItem()
        item[&apos;title&apos;] = response.xpath(&apos;//h1[@class=&quot;post-title u-fontSizeLargest u-md-fontSizeLarger&quot;]/text()&apos;).extract()[0].strip()    
        thumb_link = &quot;https://blog.arrow-tech.vn&quot; + response.xpath(&apos;//img[@class=&quot;post-img u-block u-marginAuto&quot;]/@src&apos;).extract()[0].strip()   
        item[&apos;thumb&apos;] = thumb_link.split(&apos;/&apos;)[-1]
        yield scrapy.Request(thumb_link,callback=self.parse_img)
        item[&apos;author&apos;] =  response.xpath(&apos;//a[@class=&quot;link link--underline u-fontWeightMedium u-textColorDarker&quot;]/text()&apos;).extract()[0].strip() 
        item[&apos;content&apos;] =  response.xpath(&apos;//div[@class=&quot;post-inner js-post-content&quot;]&apos;).extract()[0].strip() 
        yield item


    def parse_img(self, response):
        with open(&quot;img/%s&quot; % response.url.split(&apos;/&apos;)[-1], &apos;wb&apos;) as f:
            f.write(response.body)
    

    </code></pre><ul><li><strong><code>item = CrawlItem()</code> </strong>Kh&#x1EDF;i t&#x1EA1;o m&#x1ED9;t m&#x1EA3;ng d&#x1EEF; li&#x1EC7;u nh&#x1B0; &#x111;&#xE3; &#x111;&#x1EB7;c t&#x1EA3; &#x1EDF; b&#xEA;n tr&#xEA;n</li><li><code><strong>item[&apos;title&apos;] = response.xpath(&apos;//h1[@class=&quot;post-title u-fontSizeLargest u-md-fontSizeLarger&quot;]/text()&apos;).extract()[0].strip()</strong></code><strong> </strong>T&#xEC;m ki&#x1EBF;m th&#x1EBB; h1 c&#xF3; class <strong><code>post-title u-fontSizeLargest u-md-fontSizeLarger</code>&#x2003;</strong>v&#xE0; l&#x1EA5;y text c&#x1EE7;a n&#xF3; <code>text()</code> </li><li><code>thumb_link = &quot;<a href="https://blog.arrow-tech.vn/">https://blog.arrow-tech.vn</a>&quot; + response.xpath(&apos;//img[@class=&quot;post-img u-block u-marginAuto&quot;]/@src&apos;).extract()[0].strip()</code> &#xA0;L&#x1EA5;y <code>thumb_link</code> v&#x1EDB;i img c&#xF3; class <code>post-img u-block u-marginAuto</code> </li><li><code>item[&apos;thumb&apos;] = thumb_link.split(&apos;/&apos;)[-1]</code> L&#x1EA5;y tr&#x1B0;&#x1EDD;ng thumb b&#x1EB1;ng c&#xE1;c x&#x1EEF; l&#xFD; bi&#x1EBF;n thumb_link v&#x1EEB;a l&#x1EA5;y &#x111;&#x1B0;&#x1EE3;c &#x1EDF; tr&#xEA;n</li><li><code>yield scrapy.Request(thumb_link,callback=self.parse_img)</code> Th&#x1EF1;c hi&#x1EC7;n download image thumb t&#x1EEB; <code>thumb_link</code> </li></ul><p>&#x2003;&#x110;o&#x1EA1;n code d&#x1B0;&#x1EDB;i &#x111;&#xE2;y c&#xF3; ch&#x1EE9;c n&#x103;ng l&#x1B0;u &#x1EA3;nh thumb v&#xE0;o m&#xE1;y c&#x1EE7;a ch&#xFA;ng ta (&#x1EDF; &#x111;&#xE2;y m&#xEC;nh l&#x1B0;u tr&#x1EEF; v&#xE0;o th&#x1B0; m&#x1EE5;c <code>img</code> c&#xF9;ng c&#x1EA5;p v&#x1EDB;i th&#x1B0; m&#x1EE5;c project)</p><pre><code>def parse_img(self, response):
        with open(&quot;img/%s&quot; % response.url.split(&apos;/&apos;)[-1], &apos;wb&apos;) as f:
            f.write(response.body)</code></pre><ul><li><code>item[&apos;content&apos;] = &#xA0;response.xpath(&apos;//div[@class=&quot;post-inner js-post-content&quot;]&apos;).extract()[0].strip()</code> L&#x1EA5;y content v&#x1EDB;i th&#x1EBB; div c&#xF3; class l&#xE0; <code>post-inner js-post-content</code> </li></ul><p>Sau khi &#x111;&#xE3; th&#x1EF1;c hi&#x1EC7;n xong nh&#x1EEF;ng b&#x1B0;&#x1EDB;c tr&#xEA;n, ch&#x1EA1;y l&#x1EC7;nh <code>crawl</code> </p><p>L&#x1EC7;nh n&#xE0;y s&#x1EBD; l&#x1B0;u tr&#x1EEF; k&#x1EBF;t qu&#x1EA3; crawl v&#xE0;o file result.json</p><pre><code>scrapy crawl crawler -o result.json </code></pre><p>B&#x1EA1;n c&#xF3; th&#x1EC3; clone v&#xED; d&#x1EE5; tr&#xEA;n &#x1EDF; &#x111;&#xE2;y &#x111;&#x1EC3; d&#xF9;ng th&#x1EED;</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/phobrv/demo_use_scrapy.git?ref=blog.arrow-tech.vn"><div class="kg-bookmark-content"><div class="kg-bookmark-title">phobrv/demo_use_scrapy</div><div class="kg-bookmark-description">Demo use Scrapy to crawler website data. Contribute to phobrv/demo_use_scrapy development by creating an account on GitHub.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.githubassets.com/favicon.ico" alt="H&#x1B0;&#x1EDB;ng d&#x1EAB;n crawl website v&#x1EDB;i Scrapy"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">phobrv</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://avatars0.githubusercontent.com/u/9550597?s=400&amp;v=4" alt="H&#x1B0;&#x1EDB;ng d&#x1EAB;n crawl website v&#x1EDB;i Scrapy"></div></a></figure>]]></content:encoded></item><item><title><![CDATA[Hướng dẫn sử dụng tool Auditd để giám sát hoạt động User trên Ubuntu Server]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p><em>M&#x1ED9;t ng&#xE0;y &#x111;&#x1EB9;p tr&#x1EDD;i kh&#xE1;ch h&#xE0;ng y&#xEA;u c&#x1EA7;u h&#xE0;ng th&#xE1;ng ph&#x1EA3;i c&#xF3; report v&#x1EC1; ho&#x1EA1;t &#x111;&#x1ED9;ng c&#x1EE7;a ssh user tr&</em></p>]]></description><link>https://blog.arrow-tech.vn/huong-dan-su-dung-tool-auditd-de-giam-sat-hoat-dong-user-tren-ubuntu-server-2/</link><guid isPermaLink="false">63915acd7a2f410001205ded</guid><category><![CDATA[ubuntu]]></category><category><![CDATA[Security]]></category><category><![CDATA[auditd]]></category><dc:creator><![CDATA[Quang Dang]]></dc:creator><pubDate>Wed, 12 Jun 2019 07:35:51 GMT</pubDate><media:content url="https://blog.arrow-tech.vn/content/images/2019/06/1_Gmpq3RbI2TvL344DdAg55w-1.png" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://blog.arrow-tech.vn/content/images/2019/06/1_Gmpq3RbI2TvL344DdAg55w-1.png" alt="H&#x1B0;&#x1EDB;ng d&#x1EAB;n s&#x1EED; d&#x1EE5;ng tool Auditd &#x111;&#x1EC3; gi&#xE1;m s&#xE1;t ho&#x1EA1;t &#x111;&#x1ED9;ng User tr&#xEA;n Ubuntu Server"><p><em>M&#x1ED9;t ng&#xE0;y &#x111;&#x1EB9;p tr&#x1EDD;i kh&#xE1;ch h&#xE0;ng y&#xEA;u c&#x1EA7;u h&#xE0;ng th&#xE1;ng ph&#x1EA3;i c&#xF3; report v&#x1EC1; ho&#x1EA1;t &#x111;&#x1ED9;ng c&#x1EE7;a ssh user tr&#xEA;n server. Loay hoay h&#x1EBF;t m&#x1EA5;y h&#xF4;m google search, cu&#x1ED1;i c&#xF9;ng t&#xEC;m &#x111;&#x1B0;&#x1EE3;c em n&#xE0;y, th&#x1EA5;y c&#x169;ng kh&#xE1; ngon , vi&#x1EBF;t l&#xEA;n &#x111;&#xE2;y chia s&#x1EBB; v&#x1EDB;i a/e.</em></p>
<h2 id="vyauditlg">V&#x1EAD;y Audit l&#xE0; g&#xEC;?</h2>
<p>&#x110;&#x1A1;n gi&#x1EA3;n &#x111;&#x1EC3; hi&#x1EC3;u, auditd l&#xE0; m&#x1ED9;t th&#x1EB1;ng d&#x1ECB;ch v&#x1EE5; ch&#x1EA1;y ng&#x1EA7;m (audit deamon) ch&#x1ECB;u tr&#xE1;ch nhi&#x1EC7;m ghi l&#x1EA1;i t&#x1EA5;t c&#x1EA3; ho&#x1EA1;t &#x111;&#x1ED9;ng c&#x1EE7;a h&#x1EC7; th&#x1ED1;ng , ng&#x1B0;&#x1EDD;i d&#xF9;ng ... Theo nh&#x1B0; google search th&#xEC; c&#xF3; v&#x1EBB; audit &#x111;&#x1B0;&#x1EE3;c t&#xED;ch h&#x1EE3;p m&#x1EB7;c &#x111;&#x1ECB;nh tr&#xEA;n h&#x1EA7;u Linux operating system.<br>
H&#x1EA7;u h&#x1EBF;t th&#xF4;i ch&#x1EE9; kh&#xF4;ng ph&#x1EA3;i l&#xE0; t&#x1EA5;t c&#x1EA3;, trong tr&#x1B0;&#x1EDD;ng h&#x1EE3;p m&#xEC;nh ph&#x1EA3;i ti&#x1EBF;n h&#xE0;nh c&#xE0;i &#x111;&#x1EB7;t :))</p>
<h2 id="citauditnhthno">C&#xE0;i &#x111;&#x1EB7;t audit nh&#x1B0; th&#x1EBF; n&#xE0;o?</h2>
<ul>
<li>
<p>B&#x1EA1;n c&#xF3; th&#x1EC3; google search v&#x1EDB;i keyword <code>Installing the Linux Audit System on ...</code>. C&#xF2;n n&#x1EBF;u kh&#xF4;ng th&#xEC; c&#xF3; th&#x1EC3; tham kh&#x1EA3;o t&#x1EA1;i &#x111;&#xE2;y (Trong tr&#x1B0;&#x1EDD;ng h&#x1EE3;p n&#xE0;y m&#xEC;nh d&#xF9;ng Ubuntu Server 18).</p>
<pre><code>sudo apt install -y auditd audispd-plugins
</code></pre>
</li>
<li>
<p>C&#xE1;c c&#x1EA5;u h&#xEC;nh s&#x1EBD; &#x111;&#x1B0;&#x1EE3;c l&#x1B0;u trong folder <code>/etc/audit</code></p>
</li>
<li>
<p>&#x110;&#x1EC3; th&#x1EF1;c hi&#x1EC7;n log ho&#x1EA1;t &#x111;&#x1ED9;ng c&#x1EE7;a t&#x1EA5;t c&#x1EA3; ng&#x1B0;&#x1EDD;i d&#xF9;ng:</p>
<ul>
<li>M&#x1EDF; file <code>nano /etc/audit/rules.d/audit.rules</code></li>
<li>Th&#xEA;m 2 d&#xF2;ng b&#xEA;n d&#x1B0;&#x1EDB;i v&#xE0;o cu&#x1ED1;i file</li>
</ul>
<pre><code>-a exit,always -F arch=b64 -S execve
-a exit,always -F arch=b32 -S execve
</code></pre>
<ul>
<li>Sau &#x111;&#xF3; restart v&#x1EDB;i l&#x1EC7;nh <code>sudo service auditd restart</code></li>
<li>M&#x1EB7;c &#x111;&#x1ECB;nh log s&#x1EBD; &#x111;&#x1B0;&#x1EE3;c l&#x1B0;u tr&#x1EEF; &#x1EDF;  <code>/var/log/audit/audit.log</code>. Ho&#x1EB7;c c&#xF3; th&#x1EC3; c&#x1EA5;u h&#xEC;nh trong file /etc/audit/auditd.conf</li>
</ul>
</li>
</ul>
<p>Ok v&#x1EAD;y l&#xE0; c&#x1A1; b&#x1EA3;n h&#x1EC7; th&#x1ED1;ng &#x111;&#xE3; &#x111;&#x1B0;&#x1EE3;c gi&#xE1;m s&#xE1;t b&#x1EDF;i audit r&#x1ED3;i. Gi&#x1EDD; ch&#xFA;ng ta s&#x1EBD; t&#xEC;m hi&#x1EC3;u qua c&#xE1;ch &#x111;&#x1EC3; s&#x1EED; d&#x1EE5;ng audit.</p>
<h2 id="sdngauditdnhthno">S&#x1EED; d&#x1EE5;ng <code>auditd</code> nh&#x1B0; th&#x1EBF; n&#xE0;o ?</h2>
<ul>
<li>
<p>3 ti&#x1EC7;n &#xED;ch hay d&#xF9;ng:</p>
<ul>
<li>auditctl &#x2013; 1 ti&#x1EC7;n &#xED;ch &#x111;&#x1EC3; ki&#x1EC3;m so&#xE1;t h&#x1EC7; th&#x1ED1;ng kernel audit</li>
<li>ausearch &#x2013; 1 ti&#x1EC7;n &#xED;ch cho vi&#x1EC7;c t&#xEC;m ki&#x1EBF;m c&#xE1;c audit log v&#x1EDB;i c&#xE1;c event &#x111;&#x1EB7;c bi&#x1EC7;t.</li>
<li>aureport &#x2013; 1 ti&#x1EC7;n &#xED;ch &#x111;&#x1EC3; t&#x1EA1;o c&#xE1;c b&#xE1;o c&#xE1;o v&#x1EC1; s&#x1EF1; ki&#x1EC7;n &#x111;&#x1B0;&#x1EE3;c ghi l&#x1EA1;i.</li>
</ul>
</li>
<li>
<p>C&#xE1;c th&#xF4;ng s&#x1ED1; trong logs:</p>
<ul>
<li><code>time</code> - is when the audit is done</li>
<li><code>name</code> - is the object name to be audited</li>
<li><code>cwd</code> - is the current directory</li>
<li><code>syscall</code> - is related syscall</li>
<li><code>auid</code> - is the audit user ID</li>
<li><code>uid</code> and <code>gid</code> -  User ID and Group ID<br>
...</li>
</ul>
</li>
<li>
<p>C&#xE1;c l&#x1EC7;nh aureport hay d&#xF9;ng:</p>
<ul>
<li><code>sudo aureport -au</code> : Report about authentication attempts</li>
<li><code>sudo aureport -m</code>: Report all events related to account modification<br>
...</li>
<li>Xem th&#xEA;m t&#x1EA1;i <code>sudo man aureport</code></li>
</ul>
</li>
<li>
<p>C&#xE1;c l&#x1EC7;nh ausearch hay d&#xF9;ng:</p>
<ul>
<li><code>ausearch -m USER_AUTH</code> -  Xem c&#xE1;c n&#x1ED9;i dung li&#xEA;n quan &#x111;&#x1EBF;n authentication</li>
<li><code>ausearch -m USER_CMD</code> -  Xem c&#xE1;c n&#x1ED9;i dung li&#xEA;n quan &#x111;&#x1EBF;n l&#x1EC7;nh m&#xE0; user th&#x1B0;c hi&#x1EC7;n<br>
... Xem th&#xEA;m t&#x1EA1;i <code>ausearch -m</code></li>
<li><code>man ausearch this-month</code> - (today,this-week,this-mounth ...) Xem t&#x1EA5;t c&#x1EA3; c&#xE1;c log trong th&#xE1;ng.</li>
<li><code>man ausearch this-month --file csv &gt; audit.csv</code> - Export log trong th&#xE1;ng ra file CSV.</li>
<li>... Xem th&#xEA;m t&#x1EA1;i <code>sudo man ausearch</code></li>
</ul>
</li>
</ul>
<h2 id="mtviscriptshuchnucn">M&#x1ED9;t v&#xE0;i scripts h&#x1EEF;u &#xED;ch n&#x1EBF;u c&#x1EA7;n.</h2>
<p>Export CSV per month.</p>
<pre><code>#!/bin/bash

#Current date time
CURRENT_DATE=`date +&quot;%Y%m%d&quot;`

#Create folder to store
rm -rf ${CURRENT_DATE}
mkdir ${CURRENT_DATE}
cd ${CURRENT_DATE}

#Export authentication log per month
sudo ausearch -m USER_AUTH -ts this-month --format default &gt; ${CURRENT_DATE}_audit_auth.txt

#Export detail log per month
sudo ausearch  -m USER_CMD -ts this-month --format csv &gt; ${CURRENT_DATE}_audit_detail.csv
</code></pre>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Style Guide for Angular]]></title><description><![CDATA[<h2 id="l-i-m-u">L&#x1EDD;i m&#x1EDF; &#x111;&#x1EA7;u</h2><p>Angular l&#xE0; m&#x1ED9;t trong nh&#x1EEF;ng Framework c&#xF3; s&#x1EE9;c &#x1EA3;nh h&#x1B0;&#x1EDF;ng l&#x1EDB;n trong vi&#x1EC7;c thi&#x1EBF;t k&#x1EBF; &#x1EE9;ng d&#x1EE5;ng &#x1EDF; ph&#xED;</p>]]></description><link>https://blog.arrow-tech.vn/style-guide-angular-2/</link><guid isPermaLink="false">63915acd7a2f410001205deb</guid><category><![CDATA[Angular]]></category><category><![CDATA[Style Guide]]></category><category><![CDATA[Code Convention]]></category><dc:creator><![CDATA[Quang Dang]]></dc:creator><pubDate>Mon, 25 Feb 2019 03:09:08 GMT</pubDate><media:content url="https://blog.arrow-tech.vn/content/images/2019/02/1_XZiWn4Ej-ZfJ6Pxj-b9AkQ-1.png" medium="image"/><content:encoded><![CDATA[<h2 id="l-i-m-u">L&#x1EDD;i m&#x1EDF; &#x111;&#x1EA7;u</h2><img src="https://blog.arrow-tech.vn/content/images/2019/02/1_XZiWn4Ej-ZfJ6Pxj-b9AkQ-1.png" alt="Style Guide for Angular"><p>Angular l&#xE0; m&#x1ED9;t trong nh&#x1EEF;ng Framework c&#xF3; s&#x1EE9;c &#x1EA3;nh h&#x1B0;&#x1EDF;ng l&#x1EDB;n trong vi&#x1EC7;c thi&#x1EBF;t k&#x1EBF; &#x1EE9;ng d&#x1EE5;ng &#x1EDF; ph&#xED;a Client Side. N&#xF3; r&#x1EA5;t m&#x1EA1;nh m&#x1EBD; b&#x1EDF;i c&#xF3; th&#xE0;nh ph&#x1EA7;n nh&#x1B0; h&#x1EC7; th&#x1ED1;ng qu&#x1EA3;n l&#xFD; routing, dependency injection, two-way binding,..</p><p>Vi&#x1EC7;c s&#x1EED; d&#x1EE5;ng Angular kh&#xE1; &#x111;&#x1A1;n gi&#x1EA3;n b&#x1EDF;i c&#x1ED9;ng &#x111;&#x1ED3;ng h&#x1ED7; tr&#x1EE3; kh&#xE1; nhi&#x1EC1;u v&#xE0; nh&#x1EEF;ng ki&#x1EBF;n th&#x1EE9;c tr&#xEA;n trang ch&#x1EE7; <a href="https://angular.io/?ref=blog.arrow-tech.vn">angular.io</a> cung c&#x1EA5;p kh&#xE1; &#x111;&#x1EA7;y &#x111;&#x1EE7;. B&#x1EA1;n c&#xF3; th&#x1EC3; d&#x1EF1;a theo lu&#x1ED3;ng h&#x1B0;&#x1EDB;ng d&#x1EAB;n v&#xE0; t&#x1EEB; &#x111;&#xF3; vi&#x1EBF;t m&#x1ED9;t &#x1EE9;ng d&#x1EE5;ng demo d&#x1EC5; d&#xE0;ng.</p><!--kg-card-begin: markdown--><p>M&#x1ED9;t ng&#x1B0;&#x1EDD;i l&#x1EAD;p tr&#xEC;nh vi&#xEA;n gi&#x1ECF;i kh&#xF4;ng ch&#x1EC9; th&#xE0;nh th&#x1EA1;o c&#xE1;c framework v&#xE0; c&#xF4;ng ngh&#x1EC7; m&#x1EDB;i m&#xE0; c&#xF2;n ph&#x1EA3;i qu&#x1EA3;n l&#xFD; v&#xE0; c&#x1EA5;u tr&#xFA;c code sao cho t&#x1ED1;t nh&#x1EA5;t. K&#x1EBF;t qu&#x1EA3; l&#xE0; code c&#x1EE7;a ch&#xFA;ng ta ph&#x1EA3;i c&#xF3; t&#xED;nh t&#xE1;i s&#x1EED; d&#x1EE5;ng, d&#x1EC5; &#x111;&#x1ECD;c, d&#x1EC5; m&#x1EDF; r&#x1ED9;ng, d&#x1EC5; qu&#x1EA3;n l&#xFD; v&#xE0; ti&#x1EBF;t ki&#x1EC7;m &#x111;&#x1B0;&#x1EE3;c th&#x1EDD;i gian debug.</p>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><p>L&#xE0; m&#x1ED9;t dev v&#xE0; &#xED;t nhi&#x1EC1;u th&#x1EDD;i gian t&#xEC;m hi&#x1EC3;u c&#xF4;ng ngh&#x1EC7; (framework Angular 7), h&#xF4;m nay t&#xF4;i s&#x1EBD; n&#xEA;u ra m&#x1ED9;t s&#x1ED1; style guide cho Angular cho m&#x1ECD;i ng&#x1B0;&#x1EDD;i c&#xF9;ng nghi&#xEA;n c&#x1EE9;u v&#xE0; &#xE1;p d&#x1EE5;ng.</p>
<!--kg-card-end: markdown--><h2 id="m-t-s-nguy-n-t-c">M&#x1ED9;t s&#x1ED1; nguy&#xEA;n t&#x1EAF;c</h2><!--kg-card-begin: markdown--><h3 id="1ruleofone">1. Rule of One</h3>
<ul>
<li>M&#x1ED9;t component kh&#xF4;ng qu&#xE1; 400 d&#xF2;ng code</li>
<li>&#x110;&#x1EC3; thu&#x1EAD;n ti&#x1EC7;n trong vi&#x1EC7;c t&#xE1;i s&#x1EED; d&#x1EE5;ng code, hay d&#x1EC5; &#x111;&#x1ECD;c code h&#x1A1;n th&#xEC; ta n&#xEA;n chia th&#xE0;nh c&#xE1;c file service, model, module v&#xE0; component thay v&#xEC; vi&#x1EBF;t chung h&#x1EBF;t v&#xE0;o trong m&#x1ED9;t component.</li>
</ul>
<h3 id="2smallfunction">2. Small Function</h3>
<ul>
<li>M&#x1ED9;t small function gi&#x1EDB;i h&#x1EA1;n kh&#xF4;ng qu&#xE1; 75 d&#xF2;ng</li>
<li>Y&#xEA;u c&#x1EA7;u &#x111;&#x1EB7;t t&#xEA;n h&#xE0;m sao cho d&#x1EC5; &#x111;&#x1ECD;c, th&#xED;ch h&#x1EE3;p v&#x1EDB;i t&#xED;nh n&#x103;ng c&#x1EE7;a t&#x1EEB;ng h&#xE0;m.</li>
</ul>
<h3 id="3generalnamingguidelines">3. General Naming Guidelines</h3>
<ul>
<li>Khuy&#x1EBF;n kh&#xED;ch &#x111;&#x1EB7;t t&#xEA;n theo c&#x1EA5;u tr&#xFA;c: &#x201C;feature.type.file-style&#x201D;, <strong>trong &#x111;&#xF3;</strong>:<br>
+feature l&#xE0; danh t&#x1EEB; di&#x1EC5;n t&#x1EA3; &#x111;&#x1EB7;c t&#xED;nh t&#x1B0;&#x1EE3;ng tr&#x1B0;ng c&#x1EE7;a file.<br>
+type di&#x1EC5;n t&#x1EA3; ki&#x1EC3;u flie (module, service hay component).<br>
+file-style l&#xE0; t&#xEA;n &#x111;&#x1ECB;nh d&#x1EA1;ng file (ts, html hay css|scss).<br>
V&#xED; d&#x1EE5;:</li>
</ul>
<pre><code>check-list.component.ts
create-event.component.html
</code></pre>
<h3 id="4separatefilenameswithdotanddashes">4. Separate file names with dot and dashes</h3>
<ul>
<li>S&#x1EED; d&#x1EE5;ng d&#x1EA5;u &#x2018; - &#x2018; ng&#x103;n c&#xE1;ch &#x111;&#x1EB7;c t&#xED;nh t&#x1B0;&#x1EE3;ng tr&#x1B0;ng t&#xEA;n file.</li>
<li>S&#x1EED; d&#x1EE5;ng d&#x1EA5;u &#x2018; . &#x2018; &#x111;&#x1EC3; ph&#xE2;n bi&#x1EC7;t c&#xE1;c ph&#x1EA7;n trong 1 c&#x1EA5;u tr&#xFA;c &#x111;&#x1EB7;t t&#xEA;n.</li>
<li>V&#xED; d&#x1EE5;:</li>
</ul>
<pre><code>check-list.component.ts
// &apos;check-list&apos;
create-event.component.html
// &apos;create-event.component&apos;
</code></pre>
<h3 id="5symbolsandfilenamesservicenames">5. Symbols and file names / Service names</h3>
<ul>
<li>&#x110;&#x1EB7;t t&#xEA;n class t&#x1B0;&#x1A1;ng &#x1EE9;ng v&#x1EDB;i ki&#x1EC3;u file<br>
V&#xED; d&#x1EE5;: file name c&#xF3; c&#x1EA5;u tr&#xFA;c app.component.ts th&#xEC; t&#xEA;n class t&#x1B0;&#x1A1;ng &#x1EE9;ng l&#xE0; AppComponent</li>
</ul>
<pre><code>@Component({ ... })
export class AppComponent { }
--&gt; file names: app.component.ts
</code></pre>
<h3 id="6bootstrapping">6. Bootstrapping</h3>
<ul>
<li>&#x110;&#x1EB7;t bootstrapping v&#xE0; platform logic v&#xE0;o file main.ts gi&#xFA;p thu&#x1EAD;n ti&#x1EC7;n vi&#x1EC7;c kh&#x1EDF;i t&#x1EA1;o logic &#x1EE9;ng d&#x1EE5;ng v&#xE0; tu&#xE2;n th&#x1EE7; nguy&#xEA;n t&#x1EAF;c c&#xF9;ng c&#xE1;c framework kh&#xE1;c.<br>
<img src="https://blog.arrow-tech.vn/content/images/2019/02/Screen-Shot-2019-02-25-at-10.56.10-AM.png" alt="Style Guide for Angular" loading="lazy"></li>
</ul>
<h3 id="7componentselectors">7. Component selectors</h3>
<ul>
<li>S&#x1EED; d&#x1EE5;ng d&#x1EA5;u &#x2018; - &#x2018; ng&#x103;n c&#xE1;ch t&#xEA;n selector c&#x1EE7;a m&#x1ED9;t component.<br>
V&#xED; d&#x1EE5;:</li>
</ul>
<pre><code>selector: &apos;ngx-todo-list&apos; thay v&#xEC; &apos;ngxToDoList&apos;
</code></pre>
<h3 id="8componentcustomprefix">8. Component custom prefix</h3>
<ul>
<li>N&#xEA;n &#x111;&#x1EB7;t t&#xEA;n c&#xE1;c selector theo ph&#x1EA1;m vi quy&#x1EC1;n truy c&#x1EAD;p b&#x1EB1;ng vi&#x1EC7;c th&#xEA;m ti&#x1EC1;n t&#x1ED1; v&#xE0;o ph&#xED;a tr&#x1B0;&#x1EDB;c t&#xEA;n selector &#x111;&#x1ECB;nh ngh&#x129;a.<br>
V&#xED; d&#x1EE5;:</li>
</ul>
<pre><code>admin-user v&#xE0; client-user.
</code></pre>
<h3 id="9classesinterface">9. Classes / Interface</h3>
<ul>
<li>T&#xEA;n Class/Interface ph&#x1EA3;i vi&#x1EBF;t hoa ch&#x1EEF; c&#xE1;i &#x111;&#x1EA7;u ti&#xEA;n m&#x1ED7;i t&#x1EEB;.<br>
V&#xED; d&#x1EE5;:</li>
</ul>
<pre><code>export class EventService { }
</code></pre>
<h3 id="10constants">10. Constants</h3>
<ul>
<li>&#x110;&#x1ECB;nh ngh&#x129;a c&#xE1;c bi&#x1EBF;n c&#xF3; gi&#xE1; tr&#x1ECB; kh&#xF4;ng &#x111;&#x1ED5;i trong th&#x1B0; m&#x1EE5;c chung &#x2018;shared&#x2019;</li>
</ul>
<h3 id="11propertiesandmethod">11. Properties and method</h3>
<ul>
<li>T&#xEA;n c&#xE1;c ph&#x1B0;&#x1A1;ng th&#x1EE9;c ph&#x1EA3;i b&#x1EAF;t &#x111;&#x1EA7;u b&#x1EB1;ng ch&#x1EEF; c&#xE1;i vi&#x1EBF;t in th&#x1B0;&#x1EDD;ng.<br>
V&#xED; d&#x1EE5;:</li>
</ul>
<pre><code>this.timeToHide();
</code></pre>
<h3 id="12importlinespacing">12. Import line spacing</h3>
<ul>
<li>N&#xEA;n ng&#x103;n c&#xE1;ch m&#x1ED9;t d&#xF2;ng gi&#x1EEF;a th&#x1B0; vi&#x1EC7;n framework v&#x1EDB;i th&#x1B0; vi&#x1EC7;n b&#xEA;n th&#x1EE9; 3.<br>
<img src="https://blog.arrow-tech.vn/content/images/2019/02/Screen-Shot-2019-02-25-at-11.08.52-AM.png" alt="Style Guide for Angular" loading="lazy"></li>
</ul>
<h3 id="13membersequence">13. Member sequence</h3>
<ul>
<li>N&#xEA;n khai b&#xE1;o t&#xEA;n bi&#x1EBF;n theo b&#x1EA3;ng alphabet</li>
<li>N&#xEA;n comment v&#xE0; ng&#x103;n c&#xE1;ch d&#xF2;ng gi&#x1EEF;a c&#xE1;c bi&#x1EBF;n/h&#xE0;m  c&#xF3; ki&#x1EC3;u public v&#xE0; private</li>
</ul>
<h3 id="14structurecodebyliftlocateidentifyflattdry">14. Structure code By LIFT (Locate-Identify-Flat-T-DRY)</h3>
<ul>
<li>Locate: &#x110;&#x1EB7;t c&#xE1;c file li&#xEA;n quan g&#x1EA7;n v&#x1EDB;i nhau &#x111;&#x1EC3; thu&#x1EAD;n ti&#x1EC7;n cho vi&#x1EC7;c qu&#x1EA3;n l&#xFD; v&#xE0; t&#xEC;m ki&#x1EBF;m file.</li>
<li>Identify: &#x110;&#x1EB7;t t&#xEA;n t&#x1B0;&#x1A1;ng &#x1EE9;ng v&#x1EDB;i n&#x1ED9;i dung c&#x1EE7;a file &#x111;&#x1EC3; x&#xE1;c &#x111;&#x1ECB;nh m&#x1ED9;t component.</li>
<li>Flat: N&#xEA;n tr&#x1EA3;i c&#x1EA5;u tr&#xFA;c m&#x1ED9;t th&#x1B0; m&#x1EE5;c d&#xE0;i nh&#x1EA5;t c&#xF3; th&#x1EC3; nh&#x1B0;ng kh&#xF4;ng &#x111;&#x1B0;&#x1EE3;c t&#x1EA1;o d&#x1B0; th&#x1EEB;a b&#x1EB1;ng c&#xE1;ch th&#xEA;m c&#xE1;c folder ph&#x1EE5; khi folder &#x111;&#xF3; ch&#x1B0;a nhi&#x1EC1;u file kh&#xE1;c nhau.</li>
<li>T-DRY: DRY (Don&#x2019;t repeat yourself) H&#x1EA1;n ch&#x1EBF; t&#x1ED1;i &#x111;a s&#x1EF1; l&#x1EB7;p &#x111;i l&#x1EB7;p l&#x1EA1;i code.</li>
</ul>
<h3 id="15outputinputdecorator">15. Output &amp; Input Decorator</h3>
<ul>
<li>Kh&#xF4;ng &#x111;&#x1EB7;t ti&#x1EC1;n t&#x1ED1; &apos;on&apos; tr&#x1B0;&#x1EDB;c action c&#x1EA7;n emit tr&#x1EEB; khi ph&#x1EE5; v&#x1EE5; cho nghi&#x1EC7;p v&#x1EE5; c&#x1EA7;n thi&#x1EBF;t.<br>
V&#xED; d&#x1EE5;:</li>
</ul>
<pre><code>@Output() changeDate = new EventEmitter(); thay v&#xEC; &apos;onChangeDate&apos;
</code></pre>
<ul>
<li>S&#x1EED; d&#x1EE5;ng Input/Output decorator thay v&#xEC; input/output directive.</li>
</ul>
<h3 id="16putpresentationlogicinthecomponentclass">16. Put presentation logic in the component class</h3>
<ul>
<li>Vi&#x1EBF;t c&#xE1;c h&#xE0;m t&#xED;nh to&#xE1;n hay x&#x1EED; l&#xFD; logic trong component class thay v&#xEC; vi&#x1EBF;t trong template.</li>
</ul>
<h3 id="17service">17. Service</h3>
<ul>
<li>L&#xE0; m&#x1ED9;t singletons (t&#x1EE9;c l&#xE0; service l&#xE0; m&#x1ED9;t class ch&#x1EC9; t&#x1EA1;o ch&#x1EE9;a duy nh&#x1EA5;t m&#x1ED9;t th&#x1EF1;c th&#x1EC3; v&#xE0; n&#xF3; s&#x1EBD; &#x111;&#x1B0;&#x1EE3;c d&#xF9;ng, g&#x1ECD;i &#x111;&#x1EBF;n &#x1EDF; b&#x1EA5;t c&#x1EE9; &#x111;&#xE2;u qua m&#x1ED9;t bi&#x1EBF;n to&#xE0;n c&#x1EE5;c)</li>
<li>S&#x1EED; d&#x1EE5;ng Injectable Decoration khai b&#xE1;o to&#xE0;n c&#x1EE5;c thay v&#xEC; @Inject khai b&#xE1;o c&#x1EE5;c b&#x1ED9;</li>
</ul>
<!--kg-card-end: markdown--><h2 id="k-t-lu-n">K&#x1EBF;t lu&#x1EAD;n</h2><!--kg-card-begin: markdown--><p>V&#x1EAD;y l&#xE0; ch&#xFA;ng ta &#x111;&#xE3; &#x111;i&#x1EC3;m qua m&#x1ED9;t v&#xE0;i nguy&#xEA;n t&#x1EAF;c trong vi&#x1EC7;c t&#xE1;i c&#x1EA5;u tr&#xFA;c code trong Angular. Hy v&#x1ECD;ng b&#xE0;i vi&#x1EBF;t tr&#xEA;n c&#xF3; th&#x1EC3; gi&#xFA;p c&#xE1;c b&#x1EA1;n g&#x1EA7;n g&#x169;i h&#x1A1;n v&#x1EDB;i Angular &#x111;&#x1ED3;ng th&#x1EDD;i gi&#xFA;p ta c&#xF3; t&#x1B0; duy v&#x1EC1; t&#xE1;i c&#x1EA5;u tr&#xFA;c code v&#xE0; qu&#x1EA3;n l&#xFD; code t&#x1ED1;t h&#x1A1;n. H&#x1EB9;n g&#x1EB7;p l&#x1EA1;i c&#xE1;c b&#x1EA1;n &#x1EDF; c&#xE1;c b&#xE0;i vi&#x1EBF;t ti&#x1EBF;p theo.</p>
<!--kg-card-end: markdown--><h2 id="ngu-n-tham-kh-o">Ngu&#x1ED3;n tham kh&#x1EA3;o</h2><!--kg-card-begin: markdown--><p><a href="https://angular.io/guide/styleguide?ref=blog.arrow-tech.vn#toc">https://angular.io/guide/styleguide#toc</a><br>
<a href="https://itnext.io/clean-code-checklist-in-angular-%EF%B8%8F-10d4db877f74?ref=blog.arrow-tech.vn">https://itnext.io/clean-code-checklist-in-angular-&#xFE0F;-10d4db877f74</a></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[[Seri] Lập trình Xamarin - Bài 1: Tổng quan về Xamarin]]></title><description><![CDATA[<p>C&#xF4;ng ngh&#x1EC7; x&#xE2;y d&#x1EF1;ng &#x1EE9;ng d&#x1EE5;ng mobile ng&#xE0;y c&#xE0;ng ph&#xE1;t tri&#x1EC3;n b&#xF9;ng n&#x1ED5;. N&#x1EBF;u nh&#x1B0; tr&#x1B0;&#x1EDB;c &#x111;&#xE2;y, c&#xE1;c b&</p>]]></description><link>https://blog.arrow-tech.vn/gioi-thieu-ve-xamarin-2/</link><guid isPermaLink="false">63915acd7a2f410001205dea</guid><category><![CDATA[Xamarin]]></category><category><![CDATA[Android]]></category><category><![CDATA[iOS]]></category><category><![CDATA[Mobile]]></category><dc:creator><![CDATA[Quang Dang]]></dc:creator><pubDate>Thu, 13 Dec 2018 08:02:48 GMT</pubDate><media:content url="https://blog.arrow-tech.vn/content/images/2018/12/Picture1.png" medium="image"/><content:encoded><![CDATA[<img src="https://blog.arrow-tech.vn/content/images/2018/12/Picture1.png" alt="[Seri] L&#x1EAD;p tr&#xEC;nh Xamarin - B&#xE0;i 1: T&#x1ED5;ng quan v&#x1EC1; Xamarin"><p>C&#xF4;ng ngh&#x1EC7; x&#xE2;y d&#x1EF1;ng &#x1EE9;ng d&#x1EE5;ng mobile ng&#xE0;y c&#xE0;ng ph&#xE1;t tri&#x1EC3;n b&#xF9;ng n&#x1ED5;. N&#x1EBF;u nh&#x1B0; tr&#x1B0;&#x1EDB;c &#x111;&#xE2;y, c&#xE1;c b&#x1EA1;n ch&#x1EC9; c&#xF3; th&#x1EC3; s&#x1EED; d&#x1EE5;ng Java &#x111;&#x1EC3; x&#xE2;y d&#x1EF1;ng &#x1EE9;ng d&#x1EE5;ng Android hay Objective-C &#x111;&#x1EC3; x&#xE2;y d&#x1EF1;ng &#x1EE9;ng d&#x1EE5;ng iOS th&#xEC; ng&#xE0;y nay, c&#xE1;c b&#x1EA1;n ch&#x1EC9; c&#x1EA7;n bi&#x1EBF;t m&#x1ED9;t ng&#xF4;n ng&#x1EEF; b&#x1EA5;t k&#x1EF3; c&#x169;ng c&#xF3; th&#x1EC3; x&#xE2;y d&#x1EF1;ng &#x111;&#x1B0;&#x1EE3;c &#x1EE9;ng d&#x1EE5;ng mobile s&#x1EED; d&#x1EE5;ng ng&#xF4;n ng&#x1EEF; &#x111;&#xF3;. Ng&#xE0;y c&#xE0;ng c&#xF3; nhi&#x1EC1;u framework h&#x1ED7; tr&#x1EE3; vi&#x1EC7;c l&#x1EAD;p tr&#xEC;nh &#x1EE9;ng d&#x1EE5;ng mobile m&#x1ED9;t c&#xE1;ch nhanh ch&#xF3;ng ph&#x1EA3;i k&#x1EC3; &#x111;&#x1EBF;n nh&#x1B0; React Native, Flutter, NativeScript,...</p><figure class="kg-card kg-image-card"><img src="https://blog.arrow-tech.vn/content/images/2018/12/image-19.png" class="kg-image" alt="[Seri] L&#x1EAD;p tr&#xEC;nh Xamarin - B&#xE0;i 1: T&#x1ED5;ng quan v&#x1EC1; Xamarin" loading="lazy"></figure><p>Tuy nhi&#xEA;n &#x111;&#x1ED1;i v&#x1EDB;i nh&#x1EEF;ng b&#x1EA1;n y&#xEA;u th&#xED;ch Microsoft, y&#xEA;u th&#xED;ch C#, y&#xEA;u th&#xED;ch Visual Studio th&#xEC; v&#x1EAB;n lu&#xF4;n c&#xF3; m&#x1ED9;t s&#x1EF1; l&#x1EF1;a ch&#x1ECD;n h&#xE0;ng &#x111;&#x1EA7;u &#x111;&#xF3; l&#xE0; Xamarin. B&#xE0;i vi&#x1EBF;t d&#x1B0;&#x1EDB;i &#x111;&#xE2;y m&#xEC;nh s&#x1EBD; chia s&#x1EBB; nh&#x1EEF;ng hi&#x1EC3;u bi&#x1EBF;t c&#x1EE7;a m&#xEC;nh v&#x1EC1; Xamarin trong seri <a href="https://blog.arrow-tech.vn/tag/xamarin/">L&#x1EAD;p tr&#xEC;nh Xamarin</a>. Hy v&#x1ECD;ng s&#x1EBD; gi&#xFA;p c&#xE1;c b&#x1EA1;n ph&#x1EA7;n n&#xE0;o trong qu&#xE1; tr&#xEC;nh h&#x1ECD;c t&#x1EAD;p v&#xE0; l&#xE0;m vi&#x1EC7;c v&#x1EDB;i Xamarin.</p><p><em>OK! Let&apos;s GO!!!</em></p><p><strong>Xamarin l&#xE0; g&#xEC;</strong></p><!--kg-card-begin: markdown--><p>Xamarin l&#xE0; m&#x1ED9;t framework &#x111;&#x1EC3; x&#xE2;y d&#x1EF1;ng c&#xE1;c &#x1EE9;ng d&#x1EE5;ng di &#x111;&#x1ED9;ng &#x111;a n&#x1EC1;n t&#x1EA3;ng &#x111;&#x1B0;&#x1EE3;c t&#x1EA1;o ra b&#x1EDF;i h&#xE3;ng ph&#x1EA7;n m&#x1EC1;m di &#x111;&#x1ED9;ng c&#xF9;ng t&#xEA;n th&#xE0;nh l&#x1EAD;p v&#xE0;o ng&#xE0;y 16 th&#xE1;ng 5 n&#x103;m 2011 b&#x1EDF;i c&#xE1;c k&#x1EF9; s&#x1B0; &#x111;&#xE3; t&#x1EA1;o ra Mono, Mono cho Android v&#xE0; MonoTouch v&#x1EDB;i h&#x1A1;n 500 ngh&#xEC;n nh&#xE2;n l&#x1EF1;c. H&#xE3;ng n&#xE0;y s&#x1EED; d&#x1EE5;ng ng&#xF4;n ng&#x1EEF; C# &#x111;&#x1EC3; vi&#x1EBF;t c&#xE1;c &#x1EE9;ng d&#x1EE5;ng ch&#x1EA1;y tr&#xEA;n Mac, Android, &#xFD; t&#x1B0;&#x1EDF;ng tri&#x1EC3;n khai c&#xE1;c &#x1EE9;ng d&#x1EE5;ng &#x111;a n&#x1EC1;n t&#x1EA3;ng s&#x1EED; d&#x1EE5;ng Common Language Infrastructure (CLI) v&#xE0; Common Language Specifications (th&#x1B0;&#x1EDD;ng &#x111;&#x1B0;&#x1EE3;c g&#x1ECD;i l&#xE0; Microsoft .NET).<br>
&#x110;&#x1EBF;n th&#xE1;ng 11/2013, Microsoft &#x111;&#xE3; mua l&#x1EA1;i v&#xE0; t&#xED;ch h&#x1EE3;p ch&#x1EA1;y tr&#xEA;n m&#xF4;i tr&#x1B0;&#x1EDD;ng Windows 8. V&#x1EDB;i c&#x1A1; s&#x1EDF; m&#xE3; ngu&#x1ED3;n m&#x1EDF; c&#x1EE7;a C#, c&#xE1;c l&#x1EAD;p tr&#xEC;nh vi&#xEA;n c&#xF3; th&#x1EC3; s&#x1EED; d&#x1EE5;ng c&#xE1;c c&#xF4;ng c&#x1EE5; Xamarin &#x111;&#x1EC3; vi&#x1EBF;t c&#xE1;c &#x1EE9;ng d&#x1EE5;ng native Android, iOS v&#xE0; Windows v&#x1EDB;i giao di&#x1EC7;n ng&#x1B0;&#x1EDD;i d&#xF9;ng native v&#xE0; s&#x1EF1; chia s&#x1EBB; code tr&#xEA;n nhi&#x1EC1;u n&#x1EC1;n t&#x1EA3;ng, bao g&#x1ED3;m Windows v&#xE0; macOS.<br>
Theo nh&#x1B0; Xamarin c&#xF4;ng b&#x1ED1;, h&#x1A1;n 1.4 tri&#x1EC7;u l&#x1EAD;p tr&#xEC;nh vi&#xEA;n &#x111;ang s&#x1EED; d&#x1EE5;ng s&#x1EA3;n ph&#x1EA9;m c&#x1EE7;a Xamarin &#x1EDF; 120 qu&#x1ED1;c gia tr&#xEA;n to&#xE0;n th&#x1EBF; gi&#x1EDB;i t&#xED;nh &#x111;&#x1EBF;n th&#xE1;ng 4 n&#x103;m 2017</p>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.arrow-tech.vn/content/images/2018/12/image-9.png" class="kg-image" alt="[Seri] L&#x1EAD;p tr&#xEC;nh Xamarin - B&#xE0;i 1: T&#x1ED5;ng quan v&#x1EC1; Xamarin" loading="lazy"><figcaption>Qu&#xE1; tr&#xEC;nh ph&#xE1;t tri&#x1EC3;n c&#x1EE7;a Xamarin</figcaption></figure><!--kg-card-begin: markdown--><p>C&#xF4;ng c&#x1EE5; Xamarin &#x111;&#x1B0;&#x1EE3;c Microsoft gi&#x1EDB;i thi&#x1EC7;u v&#xE0;o th&#x1ECB; tr&#x1B0;&#x1EDD;ng Vi&#x1EC7;t Nam v&#xE0;o 18/04/2014 trong cho c&#x1ED9;ng &#x111;&#x1ED3;ng c&#xE1;c gi&#x1EA3;ng vi&#xEA;n c&#xE1;c tr&#x1B0;&#x1EDD;ng C&#x110;, &#x110;H t&#x1EA1;i TPHCM v&#xE0; &#x111;&#x1B0;&#x1EE3;c chuy&#x1EC3;n giao c&#xE1;c t&#xE0;i li&#x1EC7;u, b&#x1EA3;n quy&#x1EC1;n v&#x1EDB;i gi&#xE1; &#x1B0;u &#x111;&#xE3;i cho c&#xE1;c sinh vi&#xEA;n tr&#xEA;n n&#x1EC1;n Microsoft Visual Studio v&#xE0; &#x111;&#x1B0;&#x1EE3;c chuy&#xEA;n gia Microsoft demo l&#x1EAD;p tr&#xEC;nh Xamarin &#x111;&#x1EC3; app ch&#x1EA1;y tr&#xEA;n m&#xF4;i tr&#x1B0;&#x1EDD;ng iOS, Android, Windows Phone v&#xE0; Windows 8.1 v&#x1EDB;i c&#xE1;c Tools kh&#xE1;c nhau.<br>
T&#x1EA1;i s&#x1EF1; ki&#x1EC7;n Microsoft Build 2016, Microsoft c&#xF4;ng b&#xE1;o h&#x1ECD; s&#x1EBD; m&#xE3; ngu&#x1ED3;n m&#x1EDF; Xamarin SDK v&#xE0; cung c&#x1EA5;p c&#xE1;c c&#xF4;ng c&#x1EE5; &#x111;&#x1EC3; ph&#xE1;t tri&#x1EC3;n &#x1EE9;ng d&#x1EE5;ng s&#x1EED; d&#x1EE5;ng Xamarin mi&#x1EC5;n ph&#xED; tr&#xEA;n Visual Studio.</p>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.arrow-tech.vn/content/images/2018/12/image-10.png" class="kg-image" alt="[Seri] L&#x1EAD;p tr&#xEC;nh Xamarin - B&#xE0;i 1: T&#x1ED5;ng quan v&#x1EC1; Xamarin" loading="lazy"><figcaption>T&#x1EA5;t c&#x1EA3; m&#x1ECD;i th&#x1EE9; l&#xE0;m &#x111;&#x1B0;&#x1EE3;c v&#x1EDB;i Java Android hay Swift iOS th&#xEC; &#x111;&#x1EC1;u l&#xE0;m &#x111;&#x1B0;&#x1EE3;c v&#x1EDB;i C# v&#xE0; VS v&#x1EDB;i Xamarin</figcaption></figure><p><strong>Xamarin.Forms</strong></p><!--kg-card-begin: markdown--><p>Xamarin.Forms l&#xE0; m&#x1ED9;t c&#xF4;ng c&#x1EE5; gi&#xFA;p code giao di&#x1EC7;n ng&#x1B0;&#x1EDD;i d&#xF9;ng c&#xF3; th&#x1EC3; &#x111;&#x1B0;&#x1EE3;c chia s&#x1EBB; tr&#xEA;n c&#xE1;c &#x1EE9;ng d&#x1EE5;ng iOS, Android v&#xE0; Universal Windows Platform v&#x1EDB;i 100% C#. Xamarin.Forms bao g&#x1ED3;m h&#x1A1;n 40 &#x111;i&#x1EC1;u khi&#x1EC3;n v&#xE0; b&#x1ED1; c&#x1EE5;c, &#x111;&#x1B0;&#x1EE3;c &#xE1;nh x&#x1EA1; t&#x1EDB;i c&#xE1;c &#x111;i&#x1EC1;u khi&#x1EC3;n g&#x1ED1;c trong qu&#xE1; tr&#xEC;nh ch&#x1EA1;y. N&#xF3; h&#x1ED7; tr&#x1EE3; c&#xE1;c n&#x1EC1;n t&#x1EA3;ng sau:</p>
<ul>
<li>Android 4.4 +</li>
<li>iOS 8+</li>
<li>Windows 10 Universal Windows Platform<br>
Ngo&#xE0;i ra, Xamarin Forms c&#xF2;n h&#x1ED7; tr&#x1EE3; c&#xE1;c n&#x1EC1;n t&#x1EA3;ng d&#x1B0;&#x1EDB;i &#x111;&#xE2;y nh&#x1B0;ng v&#x1EAB;n &#x111;ang &#x1EDF; ch&#x1EBF; &#x111;&#x1ED9; Preview ho&#x1EB7;c do b&#xEA;n th&#x1EE9; ba ph&#xE1;t tri&#x1EC3;n:</li>
<li>Samsung Tizen</li>
<li>macOS</li>
<li>GTK#</li>
<li>WPF</li>
</ul>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.arrow-tech.vn/content/images/2018/12/image-11.png" class="kg-image" alt="[Seri] L&#x1EAD;p tr&#xEC;nh Xamarin - B&#xE0;i 1: T&#x1ED5;ng quan v&#x1EC1; Xamarin" loading="lazy"><figcaption>Danh s&#xE1;ch c&#xE1;c n&#x1EC1;n t&#x1EA3;ng Xamarin h&#x1ED7; tr&#x1EE3;</figcaption></figure><!--kg-card-begin: markdown--><p>D&#x1B0;&#x1EDB;i &#x111;&#xE2;y l&#xE0; h&#xEC;nh &#x1EA3;nh so s&#xE1;nh v&#x1EC1; chia s&#x1EBB; code c&#x1EE7;a c&#xE1;ch s&#x1EED; d&#x1EE5;ng Xamarin truy&#x1EC1;n th&#x1ED1;ng v&#xE0; s&#x1EED; d&#x1EE5;ng Xamarin.Forms. R&#xF5; r&#xE0;ng khi s&#x1EED; d&#x1EE5;ng Xamarin.Forms, ch&#xFA;ng ta &#x111;&#xE3; s&#x1EED; d&#x1EE5;ng &#x111;&#x1B0;&#x1EE3;c h&#x1EA7;u h&#x1EBF;t code chung cho to&#xE0;n b&#x1ED9; &#x1EE9;ng d&#x1EE5;ng.</p>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card"><img src="https://blog.arrow-tech.vn/content/images/2018/12/image-12.png" class="kg-image" alt="[Seri] L&#x1EAD;p tr&#xEC;nh Xamarin - B&#xE0;i 1: T&#x1ED5;ng quan v&#x1EC1; Xamarin" loading="lazy"></figure><!--kg-card-begin: markdown--><p>Giao di&#x1EC7;n c&#xE1;c &#x1EE9;ng d&#x1EE5;ng s&#x1EED; d&#x1EE5;ng Xamarin &#x111;&#x1B0;&#x1EE3;c vi&#x1EBF;t trong m&#x1ED9;t file XAML. N&#xF3; c&#xF3; c&#x1EA5;u tr&#xFA;c c&#x1EE7;a m&#x1ED9;t file XML, kh&#xE1; gi&#x1ED1;ng v&#x1EDB;i Winform hay XML c&#x1EE7;a Android.</p>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card"><img src="https://blog.arrow-tech.vn/content/images/2018/12/image-13.png" class="kg-image" alt="[Seri] L&#x1EAD;p tr&#xEC;nh Xamarin - B&#xE0;i 1: T&#x1ED5;ng quan v&#x1EC1; Xamarin" loading="lazy"></figure><!--kg-card-begin: markdown--><p>V&#x1EDB;i 1 &#x111;o&#x1EA1;n code nh&#x1B0; n&#xE0;y ch&#xFA;ng ta c&#xF3; th&#x1EC3; build ra 3 n&#x1EC1;n t&#x1EA3;ng kh&#xE1;c nhau:</p>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card"><img src="https://blog.arrow-tech.vn/content/images/2018/12/image-14.png" class="kg-image" alt="[Seri] L&#x1EAD;p tr&#xEC;nh Xamarin - B&#xE0;i 1: T&#x1ED5;ng quan v&#x1EC1; Xamarin" loading="lazy"></figure><p><strong>&#x1AF;u &#x111;i&#x1EC3;m c&#x1EE7;a Xamarin</strong></p><p><em>Chia s&#x1EBB; code &#x1EDF; m&#x1ECD;i n&#x1A1;i</em></p><!--kg-card-begin: markdown--><p>Khi vi&#x1EBF;t m&#x1ED9;t &#x1EE9;ng d&#x1EE5;ng s&#x1EED; d&#x1EE5;ng b&#x1ED9; c&#xF4;ng c&#x1EE5; c&#x1EE7;a Xamarin th&#xEC; v&#x1EC1; c&#x1A1; b&#x1EA3;n b&#x1EA1;n &#x111;ang s&#x1EED; d&#x1EE5;ng m&#x1ED9;t l&#x1EDB;p tr&#x1EEB;u t&#x1B0;&#x1EE3;ng ph&#xED;a tr&#xEA;n c&#xE1;c SDK th&#x1EF1;c s&#x1EF1; c&#x1EE7;a iOS v&#xE0; Android. &#x110;i&#x1EC1;u n&#xE0;y c&#xF3; ngh&#x129;a l&#xE0; b&#x1EA1;n s&#x1EBD; thu &#x111;&#x1B0;&#x1EE3;c k&#x1EBF;t qu&#x1EA3; l&#xE0; m&#x1ED9;t &#x1EE9;ng d&#x1EE5;ng native ho&#xE0;n to&#xE0;n v&#x1EDB;i giao di&#x1EC7;n d&#xF9;ng native tr&#xEA;n m&#x1ED7;i n&#x1EC1;n t&#x1EA3;ng.<br>
Khi b&#x1EA1;n t&#x1EA1;o &#x1EE9;ng d&#x1EE5;ng tr&#xEA;n Xamarin, b&#x1EA1;n s&#x1EED; d&#x1EE5;ng c&#xF9;ng ng&#xF4;n ng&#x1EEF;, API v&#xE0; c&#x1EA5;u tr&#xFA;c d&#x1EEF; li&#x1EC7;u &#x111;&#x1EC3; chia s&#x1EBB; trung b&#xEC;nh 75% code tr&#xEA;n t&#x1EA5;t c&#x1EA3; c&#xE1;c n&#x1EC1;n t&#x1EA3;ng &#x111;i&#x1EC7;n tho&#x1EA1;i di &#x111;&#x1ED9;ng. Logic &#x1EE9;ng d&#x1EE5;ng n&#xE0;y c&#xF3; th&#x1EC3; d&#x1EC5; d&#xE0;ng chia s&#x1EBB; tr&#xEA;n nhi&#x1EC1;u n&#x1EC1;n t&#x1EA3;ng. Qua &#x111;&#xF3; c&#xF3; th&#x1EC3; gi&#x1EA3;m &#x111;&#xE1;ng k&#x1EC3; chi ph&#xED; v&#xE0; th&#x1EDD;i gian ph&#xE1;t tri&#x1EC3;n &#x1EE9;ng d&#x1EE5;ng di &#x111;&#x1ED9;ng cho 3 n&#x1EC1;n t&#x1EA3;ng ph&#x1ED5; bi&#x1EBF;n nh&#x1EA5;t.</p>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card"><img src="https://blog.arrow-tech.vn/content/images/2018/12/image-17.png" class="kg-image" alt="[Seri] L&#x1EAD;p tr&#xEC;nh Xamarin - B&#xE0;i 1: T&#x1ED5;ng quan v&#x1EC1; Xamarin" loading="lazy"></figure><p><em>Performance nh&#x1B0; native</em></p><!--kg-card-begin: markdown--><p>Kh&#xF4;ng gi&#x1ED1;ng nh&#x1B0; ph&#x1B0;&#x1A1;ng ph&#xE1;p k&#x1EBF;t h&#x1EE3;p truy&#x1EC1;n th&#x1ED1;ng d&#x1EF1;a tr&#xEA;n c&#xE1;c c&#xF4;ng ngh&#x1EC7; web, m&#x1ED9;t &#x1EE9;ng d&#x1EE5;ng &#x111;a n&#x1EC1;n t&#x1EA3;ng &#x111;&#x1B0;&#x1EE3;c x&#xE2;y d&#x1EF1;ng v&#x1EDB;i Xamarin c&#x169;ng c&#xF3; th&#x1EC3; xem v&#xE0;o h&#xE0;ng native. C&#xE1;c s&#x1ED1; li&#x1EC7;u performances l&#xE0; t&#x1B0;&#x1A1;ng &#x111;&#x1B0;&#x1A1;ng khi so s&#xE1;nh v&#x1EDB;i c&#xE1;c s&#x1ED1; li&#x1EC7;u performance c&#x1EE7;a Java, Kotlin cho Android v&#xE0; Objective-C ho&#x1EB7;c Swift cho &#x1EE9;ng d&#x1EE5;ng ph&#xE1;t tri&#x1EC3;n &#x1EE9;ng d&#x1EE5;ng iOS native. H&#x1A1;n th&#x1EBF; n&#x1EEF;a, performance li&#xEA;n t&#x1EE5;c &#x111;&#x1B0;&#x1EE3;c c&#x1EA3;i thi&#x1EC7;n &#x111;&#x1EC3; ph&#xF9; h&#x1EE3;p ho&#xE0;n to&#xE0;n v&#x1EDB;i ti&#xEA;u chu&#x1EA9;n c&#x1EE7;a l&#x1EAD;p tr&#xEC;nh native. N&#x1EC1;n t&#x1EA3;ng Xamarin cung c&#x1EA5;p l&#xE0; gi&#x1EA3;i ph&#xE1;p &#x111;&#x1EC3; testing v&#xE0; theo d&#xF5;i ho&#x1EA1;t &#x111;&#x1ED9;ng c&#x1EE7;a &#x1EE9;ng d&#x1EE5;ng. Xamarin Test Cloud k&#x1EBF;t h&#x1EE3;p v&#x1EDB;i c&#xF4;ng c&#x1EE5; Xamarin Test Recorder cho ph&#xE9;p b&#x1EA1;n ch&#x1EA1;y c&#xE1;c UI test t&#x1EF1; &#x111;&#x1ED9;ng v&#xE0; x&#xE1;c &#x111;&#x1ECB;nh c&#xE1;c v&#x1EA5;n &#x111;&#x1EC1; v&#x1EC1; performance tr&#x1B0;&#x1EDB;c khi &#x1EE9;ng d&#x1EE5;ng release. Tuy nhi&#xEA;n, d&#x1ECB;ch v&#x1EE5; n&#xE0;y c&#xF3; t&#xED;nh ph&#xED;.<br>
H&#xEC;nh d&#x1B0;&#x1EDB;i &#x111;&#xE2;y cho ch&#xFA;ng ta th&#x1EA5;y th&#x1EDD;i gian m&#x1EDF; m&#x1ED9;t &#x1EE9;ng d&#x1EE5;ng HelloWorld b&#x1EB1;ng &#x1EE9;ng d&#x1EE5;ng native, &#x1EE9;ng d&#x1EE5;ng vi&#x1EBF;t b&#x1EB1;ng Xamarin Native, &#x1EE9;ng d&#x1EE5;ng vi&#x1EBF;t b&#x1EB1;ng Xamarin.Forms:</p>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card"><img src="https://blog.arrow-tech.vn/content/images/2018/12/image-18.png" class="kg-image" alt="[Seri] L&#x1EAD;p tr&#xEC;nh Xamarin - B&#xE0;i 1: T&#x1ED5;ng quan v&#x1EC1; Xamarin" loading="lazy"></figure><p></p><p><em>M&#x1ED9;i s&#x1ED1; &#x1B0;u &#x111;i&#x1EC3;m kh&#xE1;c</em></p><!--kg-card-begin: markdown--><p>M&#x1ED9;t s&#x1ED1; &#x111;i&#x1EC3;m c&#x1ED9;ng cho Xamarin nh&#x1B0;:</p>
<ul>
<li>C&#xF3; kh&#x1EA3; n&#x103;ng l&#x1EF1;a ch&#x1ECD;n UI layout</li>
<li>T&#xED;ch h&#x1EE3;p OAuth</li>
<li>T&#xED;ch h&#x1EE3;p REST APIs t&#x1EEB; xa</li>
<li>C&#xF4;ng ngh&#x1EC7; d&#x1EAB;n &#x111;&#x1B0;&#x1EDD;ng v&#xE0; x&#x1EED; l&#xFD; t&#xED;n hi&#x1EC7;u th&#x1EDD;i gian th&#x1EF1;c cho &#x1EE9;ng d&#x1EE5;ng &#x111;&#x1ECB;nh v&#x1ECB;</li>
<li>T&#xED;ch h&#x1EE3;p m&#x1EA1;ng x&#xE3; h&#x1ED9;i</li>
<li>C&#xF3; b&#x1ED9; c&#x1A1; s&#x1EDF; d&#x1EEF; li&#x1EC7;u SQLite nh&#xFA;ng</li>
<li>Th&#x1B0; vi&#x1EC7;n XAML cho ph&#xE9;p x&#xE2;y d&#x1EF1;ng m&#x1ED9;t lo&#x1EA1;t &#x1EE9;ng d&#x1EE5;ng</li>
<li>H&#x1ED7; tr&#x1EE3; data binding</li>
</ul>
<!--kg-card-end: markdown--><p><strong>Nh&#x1B0;&#x1EE3;c &#x111;i&#x1EC3;m c&#x1EE7;a Xamarin</strong></p><p><em>&#x1EE8;ng d&#x1EE5;ng th&#x1EF1;c hi&#x1EC7;n ch&#x1EAD;m h&#x1A1;n v&#xE0; y&#xEA;u c&#x1EA7;u nhi&#x1EC1;u dung l&#x1B0;&#x1EE3;ng h&#x1A1;n tr&#xEA;n thi&#x1EBF;t b&#x1ECB;</em></p><!--kg-card-begin: markdown--><p>&#x1EE8;ng d&#x1EE5;ng Xamarin l&#x1EDB;n h&#x1A1;n, n&#x1EB7;ng h&#x1A1;n so v&#x1EDB;i &#x1EE9;ng d&#x1EE5;ng native. So s&#xE1;nh v&#x1EDB;i &#x1EE9;ng d&#x1EE5;ng native n&#xF3; chi&#x1EBF;m nhi&#x1EC1;u h&#x1A1;n v&#xE0;i Mb so v&#x1EDB;i Java/Objective C t&#x1B0;&#x1A1;ng &#x1EE9;ng. K&#xED;ch th&#x1B0;&#x1EDB;c c&#x1EE7;a m&#x1ED9;t &#x1EE9;ng d&#x1EE5;ng code b&#x1EB1;ng xamarin l&#xE0; 3Mb, trong khi code b&#x1EB1;ng Objective C ch&#x1EC9; chi&#x1EBF;m 172 Kb. C&#xE0;ng s&#x1EED; d&#x1EE5;ng nhi&#x1EC1;u API, c&#xE0;ng nhi&#x1EC1;u l&#x1B0;u tr&#x1EEF; b&#x1ECB; chi&#x1EBF;m tr&#xEA;n thi&#x1EBF;t b&#x1ECB;.</p>
<!--kg-card-end: markdown--><p><em>Khuy&#x1EBF;t &#x111;i&#x1EC3;m c&#x1EE7;a AOT Compiler</em></p><!--kg-card-begin: markdown--><p>Xamarin Forms c&#x169;ng c&#xF3; nh&#x1EEF;ng khuy&#x1EBF;t &#x111;i&#x1EC3;m AOT compliler. N&#xF3; kh&#xF4;ng &#x111;&#x1B0;&#x1EE3;c complie c&#xE1;c &#x111;o&#x1EA1;n code g&#x1ECD;n g&#xE0;ng nh&#x1B0; Xcode. H&#x1EA1;n ch&#x1EBF; c&#x1EE7;a Xamarin &#x1EA3;nh h&#x1B0;&#x1EDF;ng &#x111;&#x1EBF;n c&#x1EA3; ph&#xE1;t tri&#x1EC3;n, test t&#x1EA3;i app l&#xEA;n store. H&#x1EA1;n ch&#x1EBF; ch&#xED;nh &#x111;&#x1ED1;i v&#x1EDB;i iOS l&#xE0; n&#xF3; kh&#xF4;ng h&#x1ED7; tr&#x1EE3; sinh code t&#x1EF1; &#x111;&#x1ED9;ng. Visual Studio biuld code l&#xE2;u. C&#xE1;i n&#xE0;y t&#x1EA5;t c&#x1EA3; c&#xE1;c l&#x1EAD;p tr&#xEC;nh vi&#xEA;n Xamarin &#x111;&#x1EC1;u &#x111;ang ph&#x1EA3;i s&#x1ED1;ng chung v&#x1EDB;i l&#x169;, m&#x1ED9;t l&#x1EA7;n build s&#x1EBD; m&#x1EA5;t r&#x1EA5;t l&#xE2;u t&#x1EEB; 3 &#x111;&#x1EBF;n 10 ph&#xFA;t cho solution v&#x1EDB;i 30 project<br>
&#x110;&#xF4;i l&#xFA;c th&#xF4;ng b&#xE1;o l&#x1ED7;i kh&#xF4;ng r&#xF5; r&#xE0;ng ch&#x1EE7; y&#x1EBF;u tr&#xEA;n Android v&#xEC; n&#xF3; l&#xE0; 1 c&#xF4;ng ngh&#x1EC7; m&#x1EDB;i n&#xEA;n v&#x1EAB;n ch&#x1B0;a &#x111;&#x1B0;&#x1EE3;c ho&#xE0;n ho&#x1EA3;n mong r&#x1EB1;ng Microsoft s&#x1EBD; fix trong t&#x1B0;&#x1A1;ng lai.</p>
<!--kg-card-end: markdown--><p><em>C&#x1ED9;ng &#x111;&#x1ED3;ng h&#x1ED7; tr&#x1EE3; &#xED;t</em></p><!--kg-card-begin: markdown--><p>C&#x1ED9;ng &#x111;&#x1ED3;ng Xamarin &#xED;t h&#x1A1;n so v&#x1EDB;i c&#x1ED9;ng &#x111;&#x1ED3;ng c&#x1EE7;a iOS hay Android n&#xEA;n &#x111;&#x1EC3; t&#xEC;m ki&#x1EBF;m &#x111;&#x1B0;&#x1EE3;c 1 developer Xamarin c&#xF3; kinh nghi&#x1EC7;m l&#xE0; chuy&#x1EC7;n kh&#xF4;ng d&#x1EC5; d&#xE0;ng g&#xEC; d&#xF9; Xamarin l&#xE0; n&#x1EC1;n t&#x1EA3;ng &#x111;&#x1B0;&#x1EE3;c ph&#xE1;t tri&#x1EC3;n nh&#x1EDD; s&#x1EF1; h&#x1ED7; tr&#x1EE3; t&#x1EEB; Microsoft. Theo nhi&#x1EC1;u ngu&#x1ED3;n th&#xF4;ng tin, c&#x1ED9;ng &#x111;&#x1ED3;ng Xamarin chi&#x1EBF;m 10% c&#x1ED9;ng &#x111;&#x1ED9;ng l&#x1EAD;p tr&#xEC;nh mobile to&#xE0;n c&#x1EA7;u d&#x1EF1;a tr&#xEA;n th&#x1EF1;c t&#x1EBF; l&#xE0; n&#x1EC1;n t&#x1EA3;ng n&#xE0;y cung c&#x1EA5;p t&#x1ED1;i &#x111;a h&#x1ED7; tr&#x1EE3; cho c&#xE1;c developer. C&#x1EE5; th&#x1EC3;, c&#xF3; m&#x1ED9;t platform gi&#xE1;o d&#x1EE5;c chuy&#xEA;n bi&#x1EC7;t t&#x1EA1;i &#x110;H Xamarin, cung c&#x1EA5;p ki&#x1EBF;n th&#x1EE9;c v&#xE0; kho&#xE1; hu&#x1EA5;n luy&#x1EC7;n cho nh&#x1EEF;ng ai m&#x1EDB;i ti&#x1EBF;p c&#x1EAD;n c&#xF4;ng ngh&#x1EC7; n&#xE0;y. K&#x1EBF;t qu&#x1EA3; l&#xE0; learning curve c&#x1EE7;a 1 engineer C#/.Net kinh nghi&#x1EC7;m s&#x1EBD; &#x111;&#x1B0;&#x1EE3;c t&#x1ED1;i thi&#x1EC3;u h&#xF3;a.</p>
<!--kg-card-end: markdown--><p><strong>K&#x1EBF;t lu&#x1EAD;n</strong></p><p>V&#x1EAD;y l&#xE0; m&#xEC;nh &#x111;&#xE3; gi&#x1EDB;i thi&#x1EC7;u v&#x1EDB;i c&#xE1;c b&#x1EA1;n m&#x1ED9;t c&#xE1;ch t&#x1ED5;ng quan v&#x1EC1; Xamarin. &#x1EDE; b&#xE0;i vi&#x1EBF;t ti&#x1EBF;p theo m&#xEC;nh s&#x1EBD; gi&#x1EDB;i thi&#x1EC7;u c&#x1EE5; th&#x1EC3; v&#x1EC1; c&#xE1;c th&#xE0;nh ph&#x1EA7;n trong gia &#x111;&#xEC;nh Xamarin. C&#xE1;c b&#x1EA1;n h&#xE3;y &#x111;&#xF3;n ch&#x1EDD; nh&#xE9;!</p>]]></content:encoded></item><item><title><![CDATA[Hot deploy wildfly 's project với intelij]]></title><description><![CDATA[<!--kg-card-begin: markdown--><h1 id="1importproject">1. Import project</h1>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/11/import_project.png" alt="import_project" loading="lazy"><br>
Ch&#x1ECD;n maven v&#xE0; next ...</p>
<h1 id="2configrunserver">2. Config run server</h1>
<p>Sau khi project import xong ch&#x1ECD;n <code>Edit Configuaration</code><br>
<img src="https://blog.arrow-tech.vn/content/images/2018/11/chon_config.png" alt="chon_config" loading="lazy"></p>
<p>T&#x1EA1;o m&#x1EDB;i v&#x1EDB;i t&#x1EEB; kh&#xF3;a <code>jboss server</code> v&#xE0; c&#x1EAD;p nh&#x1EAD;t c&#xE1;</p>]]></description><link>https://blog.arrow-tech.vn/hot-deploy-wildfly-s-project-voi-intelij/</link><guid isPermaLink="false">63915acd7a2f410001205dbc</guid><dc:creator><![CDATA[honglm]]></dc:creator><pubDate>Wed, 21 Nov 2018 11:14:14 GMT</pubDate><media:content url="https://blog.arrow-tech.vn/content/images/2018/12/wildfly_img-1-1.jpeg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><h1 id="1importproject">1. Import project</h1>
<img src="https://blog.arrow-tech.vn/content/images/2018/12/wildfly_img-1-1.jpeg" alt="Hot deploy wildfly &apos;s project v&#x1EDB;i intelij"><p><img src="https://blog.arrow-tech.vn/content/images/2018/11/import_project.png" alt="Hot deploy wildfly &apos;s project v&#x1EDB;i intelij" loading="lazy"><br>
Ch&#x1ECD;n maven v&#xE0; next ...</p>
<h1 id="2configrunserver">2. Config run server</h1>
<p>Sau khi project import xong ch&#x1ECD;n <code>Edit Configuaration</code><br>
<img src="https://blog.arrow-tech.vn/content/images/2018/11/chon_config.png" alt="Hot deploy wildfly &apos;s project v&#x1EDB;i intelij" loading="lazy"></p>
<p>T&#x1EA1;o m&#x1EDB;i v&#x1EDB;i t&#x1EEB; kh&#xF3;a <code>jboss server</code> v&#xE0; c&#x1EAD;p nh&#x1EAD;t c&#xE1;c th&#xF4;ng s&#x1ED1; theo h&#xEC;nh b&#xEA;n d&#x1B0;&#x1EDB;i<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/11/config_wildly.png" alt="Hot deploy wildfly &apos;s project v&#x1EDB;i intelij" loading="lazy"><br>
Ch&#x1EC9; &#x111;&#x1ECB;nh file war &#x111;&#x1EC3; deploy<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/11/config_filewar.png" alt="Hot deploy wildfly &apos;s project v&#x1EDB;i intelij" loading="lazy"></p>
<p>Click &apos;Ok&apos; &#x111;&#x1EC3; c&#x1EAD;p nh&#x1EAD;t<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/11/app_server-1.png" alt="Hot deploy wildfly &apos;s project v&#x1EDB;i intelij" loading="lazy"></p>
<blockquote>
<p>Ch&#xFA; &#xFD;: tr&#x1B0;&#x1EDB;c khi test code c&#x1EA7;n build l&#x1EA1;i project (Ctr+f9) or (cmd+f9)</p>
</blockquote>
<h1 id="3tngtcintelij">3. T&#x103;ng t&#x1ED1;c intelij</h1>
<p>git clone&#xA0;<a href="https://github.com/thoeni/inetTester?ref=blog.arrow-tech.vn">https://github.com/thoeni/inetTester</a><br>
<code>java -jar ./bin/inetTester.jar</code><br>
Sau khi run file jar copy hostName r&#x1ED3;i th&#xEA;m 2 d&#xF2;ng b&#xEA;n d&#x1B0;&#x1EDB;i v&#xE0;o file host <code>sudo nano /etc/hosts</code></p>
<pre><code>127.0.0.1 &lt;output-host-name&gt;.local
::1 &lt;output-host-name&gt;.local
</code></pre>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p><strong>1	T&#x1ED5;ng quan</strong></p>
<p>Cloud Vision API l&#xE0; b&#x1ED9; API &#x111;&#x1B0;&#x1EE3;c Google cung c&#x1EA5;p gi&#xFA;p c&#xE1;c l&#x1EAD;p tr&#xEC;nh vi&#xEA;n d&#x1EC5; d&#xE0;ng s&#x1EED; d&#x1EE5;ng &#x111;&#x1EC3; detect</p>]]></description><link>https://blog.arrow-tech.vn/detect-labels-faces-and-landmarks-in-images-with-the-cloud-vision-api/</link><guid isPermaLink="false">63915acd7a2f410001205db8</guid><category><![CDATA[Google Cloud]]></category><category><![CDATA[Vision]]></category><dc:creator><![CDATA[Quang Dang]]></dc:creator><pubDate>Wed, 03 Oct 2018 03:28:02 GMT</pubDate><media:content url="https://blog.arrow-tech.vn/content/images/2018/12/Picture27.png" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://blog.arrow-tech.vn/content/images/2018/12/Picture27.png" alt="Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API"><p><strong>1	T&#x1ED5;ng quan</strong></p>
<p>Cloud Vision API l&#xE0; b&#x1ED9; API &#x111;&#x1B0;&#x1EE3;c Google cung c&#x1EA5;p gi&#xFA;p c&#xE1;c l&#x1EAD;p tr&#xEC;nh vi&#xEA;n d&#x1EC5; d&#xE0;ng s&#x1EED; d&#x1EE5;ng &#x111;&#x1EC3; detect &#x1EA3;nh ch&#x1EC9; b&#x1EB1;ng m&#x1ED9;t request &#x111;&#x1A1;n gi&#x1EA3;n. B&#x1EA1;n kh&#xF4;ng c&#x1EA7;n ph&#x1EA3;i bi&#x1EBF;t Machine Learning c&#x169;ng c&#xF3; th&#x1EC3; nhanh ch&#xF3;ng t&#x1EA1;o &#x111;&#x1B0;&#x1EE3;c &#x1EE9;ng d&#x1EE5;ng detect &#x1EA3;nh b&#x1EB1;ng c&#xE1;ch s&#x1EED; d&#x1EE5;ng Cloud Vision API.</p>
<p>&quot;B&#x1EA1;n c&#x1EE9; vi&#x1EC7;c ph&#xE1;t tri&#x1EC3;n &#x1EE9;ng d&#x1EE5;ng, detect image c&#x1EE9; &#x111;&#x1EC3; Cloud Vision API lo!!!&quot;</p>
<p><strong>1.1 M&#x1EE5;c &#x111;&#xED;ch</strong></p>
<p>B&#xE0;i vi&#x1EBF;t s&#x1EBD; gi&#xFA;p b&#x1EA1;n bi&#x1EBF;t c&#xE1;c s&#x1EED; d&#x1EE5;ng Cloud Vision API &#x111;&#x1EC3; nh&#x1EAD;n d&#x1EA1;ng &#x1EA3;nh v&#x1EDB;i c&#xE1;c ch&#x1EE9;c n&#x103;ng: nh&#x1EAD;n d&#x1EA1;ng n&#x1ED9;i dung c&#x1EE7;a b&#x1EE9;c &#x1EA3;nh, nh&#x1EAD;n d&#x1EA1;ng khu&#xF4;n m&#x1EB7;t ng&#x1B0;&#x1EDD;i, nh&#x1EAD;n d&#x1EA1;ng c&#xF4;ng tr&#xEC;nh n&#x1ED5;i ti&#x1EBF;ng, nh&#x1EAD;n d&#x1EA1;ng ch&#x1EEF; vi&#x1EBF;t,...<br>
M&#xEC;nh s&#x1EBD; h&#x1B0;&#x1EDB;ng d&#x1EAB;n c&#xE1;c b&#x1EA1;n s&#x1EED; d&#x1EE5;ng theo 2 c&#xE1;ch:</p>
<ul>
<li>C&#xE1;ch 1: S&#x1EED; d&#x1EE5;ng curl &#x111;&#x1EC3; t&#x1EA1;o request t&#x1EDB;i Cloud Vision API tr&#xEA;n terminal</li>
<li>C&#xE1;ch 2: S&#x1EED; d&#x1EE5;ng Postman &#x111;&#x1EC3; t&#x1EA1;o request t&#x1EDB;i Cloud Vision API<br>
Cu&#x1ED1;i b&#xE0;i vi&#x1EBF;t m&#xEC;nh s&#x1EBD; demo m&#x1ED9;t app Android s&#x1EED; d&#x1EE5;ng Cloud Vision API &#x111;&#x1EC3; nh&#x1EAD;n di&#x1EC7;n n&#x1ED9;i dung b&#x1EE9;c &#x1EA3;nh.</li>
</ul>
<p><strong>1.2 C&#xF4;ng c&#x1EE5; c&#x1EA7;n thi&#x1EBF;t</strong></p>
<ul>
<li>Project Google Cloud Platform: B&#x1EA1;n c&#x1EA7;n c&#xF3; t&#xE0;i kho&#x1EA3;n Google Cloud &#x111;&#xE3; &#x111;&#x1B0;&#x1EE3;c th&#xEA;m th&#xF4;ng tin thanh to&#xE1;n (th&#x1EBB; VISA). N&#x1EBF;u b&#x1EA1;n ch&#x1B0;a c&#xF3; th&#xEC; c&#xF3; th&#x1EC3; tham gia Qwiklabs &#x111;&#x1EC3; nh&#x1EAD;n t&#xE0;i kho&#x1EA3;n s&#x1EED; d&#x1EE5;ng trong 45 ph&#xFA;t (<a href="https://qwiklabs.com/focuses/1841?parent=catalog&amp;ref=blog.arrow-tech.vn">https://qwiklabs.com/focuses/1841?parent=catalog</a>)<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture15.png" alt="Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API" loading="lazy"></li>
<li>Tr&#xEC;nh duy&#x1EC7;t Chrome ho&#x1EB7;c Firefox</li>
</ul>
<p><strong>2	C&#xE0;i &#x111;&#x1EB7;t chung</strong></p>
<p>&#x110;&#x1EA7;u ti&#xEA;n, b&#x1EA1;n m&#x1EDF; project c&#x1EE7;a b&#x1EA1;n. N&#x1EBF;u b&#x1EA1;n ch&#x1B0;a c&#xF3; th&#xEC; hay t&#x1EA1;o m&#x1ED9;t project m&#x1EDB;i nh&#xE9;.<br>
Giao di&#x1EC7;n project s&#x1EBD; nh&#x1B0; sau:<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture16.png" alt="Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API" loading="lazy"></p>
<p><strong>2.1	Terminal</strong></p>
<p>&#x110;&#x1EC3; m&#x1EDF; terminal, b&#x1EA1;n nh&#x1EA5;n v&#xE0;o bi&#x1EC3;u t&#x1B0;&#x1EE3;ng d&#x1B0;&#x1EDB;i &#x111;&#xE2;y tr&#xEA;n thanh navigation:<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture17.png" alt="Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API" loading="lazy"><br>
Sau &#x111;&#xF3; b&#x1EA1;n ch&#x1ECD;n START CLOUD SHELL &#x111;&#x1EC3; m&#x1EDF; terminal v&#xE0; vui l&#xF2;ng &#x111;&#x1EE3;i m&#x1ED9;t ch&#xFA;t &#x111;&#x1EC3; tr&#xEC;nh duy&#x1EC7;t c&#x1EE7;a b&#x1EA1;n k&#x1EBF;t n&#x1ED1;i v&#x1EDB;i server c&#x1EE7;a Google.<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture18.png" alt="Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API" loading="lazy"><br>
M&#xEC;nh s&#x1EBD; gi&#x1EDB;i thi&#x1EC7;u qua m&#x1ED9;t ch&#xFA;t v&#x1EC1; terminal n&#xE0;y. Terminal n&#xE0;y th&#x1EF1;c ch&#x1EA5;t gi&#x1ED1;ng nh&#x1B0; terminal (CMD, Windows Power Shell) tr&#xEA;n m&#xE1;y b&#x1EA1;n. Tr&#xEA;n &#x111;&#xF3; &#x111;&#xE3; &#x111;&#x1B0;&#x1EE3;c Google c&#xE0;i &#x111;&#x1EB7;t s&#x1EB5;n c&#xE1;c m&#xF4;i tr&#x1B0;&#x1EDD;ng &#x111;&#x1EC3; b&#x1EA1;n s&#x1EED; d&#x1EE5;ng. B&#x1EA1;n c&#xF3; th&#x1EC3; s&#x1EED; d&#x1EE5;ng t&#x1EA5;t c&#x1EA3; c&#xE1;c l&#x1EC7;nh tr&#xEA;n ubuntu nh&#x1B0; tr&#xEA;n m&#xE1;y th&#x1EAD;t c&#x1EE7;a b&#x1EA1;n.<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture19.png" alt="Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API" loading="lazy"><br>
B&#x1EA1;n c&#x169;ng c&#xF3; th&#x1EC3; s&#x1EED; d&#x1EE5;ng tr&#x1EF1;c ti&#x1EBF;p Terminal th&#x1EAD;t tr&#xEA;n m&#xE1;y c&#x1EE7;a b&#x1EA1;n &#x111;&#x1EC3; th&#x1EF1;c h&#xE0;nh. Nh&#x1B0;ng b&#x1EA1;n c&#x1EA7;n ph&#x1EA3;i c&#xE0;i 1 s&#x1ED1; c&#xF4;ng c&#x1EE5; cho n&#xF3; n&#x1EBF;u ch&#x1B0;a c&#xF3; nh&#x1B0; curl, tr&#xEC;nh ch&#x1EC9;nh s&#x1EED;a v&#x103;n b&#x1EA3;n (nano, vim,...)</p>
<p><strong>2.2	API Key</strong></p>
<p>&#x110;&#x1EC3; s&#x1EED; d&#x1EE5;ng b&#x1EA5;t k&#x1EF3; d&#x1ECB;ch v&#x1EE5; n&#xE0;o c&#x1EE7;a Google, b&#x1EA1;n c&#x169;ng &#x111;&#x1EC1;u c&#x1EA7;n ph&#x1EA3;i c&#xF3; API Key.<br>
&#x110;&#x1EC3; t&#x1EA1;o API Key, b&#x1EA1;n v&#xE0;o menu ch&#x1ECD;n APIs &amp; Services r&#x1ED3;i ch&#x1ECD;n Credentials nh&#x1B0; h&#xEC;nh d&#x1B0;&#x1EDB;i &#x111;&#xE2;y:<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture20.png" alt="Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API" loading="lazy"><br>
Sau &#x111;&#xF3; b&#x1EA1;n click Create credentials:<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture21.png" alt="Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API" loading="lazy"><br>
Trong menu x&#x1ED5; xu&#x1ED1;ng, b&#x1EA1;n ch&#x1ECD;n API key:<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture22.png" alt="Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API" loading="lazy"><br>
M&#x1ED9;t h&#x1ED9;p tho&#x1EA1;i hi&#x1EC7;n ra, b&#x1EA1;n ch&#x1ECD;n RESTRICT KEY &#x111;&#x1EC3; l&#x1B0;u l&#x1EA1;i.<br>
Ti&#x1EBF;p theo b&#x1EA1;n c&#x1EA7;n t&#x1EA1;o bi&#x1EBF;n m&#xF4;i tr&#x1B0;&#x1EDD;ng API_KEY &#x111;&#x1EC3; sau n&#xE0;y b&#x1EA1;n g&#x1ECD;i &#x111;&#x1EBF;n Cloud API th&#xEC; ch&#x1EC9; c&#x1EA7;n g&#x1ECD;i bi&#x1EBF;n &#x111;&#xF3; ra th&#xF4;i kh&#xF4;ng c&#x1EA7;n v&#xE0;o copy &#x111;o&#x1EA1;n key d&#xE0;i d&#xE0;i n&#xE0;y n&#x1EEF;a.<br>
&#x110;&#x1EC3; t&#x1EA1;o bi&#x1EBF;n m&#xF4;i tr&#x1B0;&#x1EDD;ng API_KEY, tr&#xEA;n terminal, b&#x1EA1;n g&#xF5;: export API_KEY=xxx<br>
(Trong &#x111;&#xF3; xxx l&#xE0; key m&#xE0; b&#x1EA1;n v&#x1EEB;a t&#x1EA1;o)<br>
B&#x1EA1;n c&#xF3; th&#x1EC3; check xem bi&#x1EBF;n &#x111;&#xF3; &#x111;&#xE3; &#x111;&#x1B0;&#x1EE3;c t&#x1EA1;o &#x111;&#xFA;ng ch&#x1B0;a b&#x1EB1;ng l&#x1EC7;nh sau: echo $API_KEY<br>
Nh&#x1B0; v&#x1EAD;y &#x111;&#xE3; xong, ch&#xFA;ng ta chuy&#x1EC3;n sang b&#x1B0;&#x1EDB;c ti&#x1EBF;p theo.</p>
<p><strong>2.3	T&#x1EA1;o file request.json</strong></p>
<p>File request.json n&#xE0;y s&#x1EBD; l&#xE0; body c&#x1EE7;a request t&#x1EDB;i Cloud API &#x1EDF; b&#x1B0;&#x1EDB;c ti&#x1EBF;p theo.<br>
&#x110;&#x1EC3; t&#x1EA1;o file n&#xE0;y, tr&#xEA;n terminal c&#xE1;c b&#x1EA1;n g&#xF5; touch request.json<br>
&#x110;&#x1EC3; ch&#x1EC9;nh s&#x1EED;a c&#xE1;c b&#x1EA1;n c&#xF3; th&#x1EC3; d&#xF9;ng l&#x1EC7;nh: nano request.json<br>
File n&#xE0;y s&#x1EBD; c&#xF3; d&#x1EA1;ng json nh&#x1B0; sau:<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture23.png" alt="Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API" loading="lazy"><br>
M&#xEC;nh s&#x1EBD; gi&#x1EA3;i th&#xED;ch m&#x1ED9;t s&#x1ED1; tr&#x1B0;&#x1EDD;ng trong file n&#xE0;y:</p>
<ul>
<li>requests: l&#xE0; m&#x1ED9;t m&#x1EA3;ng. Nh&#x1B0; v&#x1EAD;y Cloud API cho ph&#xE9;p b&#x1EA1;n c&#xF9;ng l&#xFA;c detect nhi&#x1EC1;u &#x1EA3;nh trong 1 request.</li>
<li>image: l&#xE0; &#x1EA3;nh c&#x1EE7;a b&#x1EA1;n. B&#x1EA1;n c&#xF3; th&#x1EC3; s&#x1EED; d&#x1EE5;ng 3 c&#xE1;ch:</li>
</ul>
<ul>
<li>C&#xE1;ch 1: D&#xF9;ng &#x1EA3;nh base64:<br>
B&#x1EA1;n c&#xF3; th&#x1EC3; v&#xE0;o c&#xE1;c trang gi&#xFA;p m&#xE3; h&#xF3;a &#x1EA3;nh c&#x1EE7;a b&#x1EA1;n d&#x1B0;&#x1EDB;i d&#x1EA1;ng base64, sau &#x111;&#xF3; b&#x1EA1;n copy &#x111;o&#x1EA1;n text k&#x1EBF;t qu&#x1EA3; &#x111;&#xF3; v&#xE0;o ph&#x1EA7;n value c&#x1EE7;a content nh&#x1B0; h&#xEC;nh sau:<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture24.png" alt="Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API" loading="lazy"><br>
N&#x1EBF;u &#x111;o&#x1EA1;n text m&#xE0; c&#xF3; data:image/jpeg;base64, &#x1EDF; &#x111;&#x1EA7;u th&#xEC; b&#x1EA1;n nh&#x1EDB; b&#x1ECF; &#x111;i nh&#xE9;!</li>
<li>C&#xE1;ch 2: D&#xF9;ng Google Cloud Storage:<br>
Ph&#x1EA7;n n&#xE0;y kh&#xE1; ph&#x1EE9;c t&#x1EA1;p n&#xEA;n b&#x1EA1;n c&#xF3; th&#x1EC3; tham kh&#x1EA3;o t&#x1EA1;i link sau: <a href="https://cloud.google.com/vision/docs?ref=blog.arrow-tech.vn">https://cloud.google.com/vision/docs</a><br>
<img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture25.png" alt="Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API" loading="lazy"></li>
<li>C&#xE1;ch 3: D&#xF9;ng tr&#x1EF1;c ti&#x1EBF;p &#x111;&#x1B0;&#x1EDD;ng link &#x1EA3;nh<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture26.png" alt="Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API" loading="lazy"></li>
</ul>
<ul>
<li>features: l&#xE0; m&#x1ED9;t m&#x1EA3;ng c&#xE1;c thu&#x1ED9;c t&#xED;nh. V&#xED; d&#x1EE5; type l&#xE0; ki&#x1EC3;u detect, maxResults l&#xE0; s&#x1ED1; k&#x1EBF;t qu&#x1EA3; t&#x1ED1;i &#x111;a tr&#x1EA3; v&#x1EC1;,&#x2026;</li>
<li>type l&#xE0; ki&#x1EC3;u m&#xE0; b&#x1EA1;n mu&#x1ED1;n Google detect. Hi&#x1EC7;n t&#x1EA1;i, Google h&#x1ED7; tr&#x1EE3; c&#xE1;c ki&#x1EC3;u sau:</li>
</ul>
<ul>
<li>TEXT_DETECTION: nh&#x1EAD;n d&#x1EA1;ng text, c&#xF3; h&#x1ED7; tr&#x1EE3; d&#x1ECB;ch sang ng&#xF4;n ng&#x1EEF; kh&#xE1;c</li>
<li>DOCUMENT_TEXT_DETECTION: nh&#x1EAD;n d&#x1EA1;ng &#x111;o&#x1EA1;n text</li>
<li>LABEL_DETECTION: nh&#x1EAD;n d&#x1EA1;ng n&#x1ED9;i dung c&#x1EE7;a b&#x1EE9;c &#x1EA3;nh</li>
<li>CROP_HINTS: crop b&#x1EE9;c &#x1EA3;nh t&#x1EAD;p trung v&#xE0;o v&#x1EAD;t tr&#x1ECD;ng t&#xE2;m hay khu&#xF4;n m&#x1EB7;t</li>
<li>FACE_DETECTION: nh&#x1EAD;n d&#x1EA1;ng khu&#xF4;n m&#x1EB7;t</li>
<li>IMAGE_PROPERTIES: c&#xE1;c thu&#x1ED9;c t&#xED;nh c&#x1EE7;a b&#x1EE9;c &#x1EA3;nh nh&#x1B0; RGB, pixcel,...</li>
<li>LANDMARK_DETECTION: nh&#x1EAD;n d&#x1EA1;ng c&#xF4;ng tr&#xEC;nh n&#x1ED5;i ti&#x1EBF;ng</li>
<li>LOGO_DETECTION: nh&#x1EAD;n d&#x1EA1;ng logo, s&#x1EA3;n ph&#x1EA9;m n&#x1ED5;i ti&#x1EBF;ng</li>
<li>SAFE_SEARCH_DETECTION: nh&#x1EAD;n d&#x1EA1;ng xem b&#x1EE9;c &#x1EA3;nh c&#xF3; n&#x1ED9;i dung an to&#xE0;n hay kh&#xF4;ng</li>
<li>WEB_DETECTION: ph&#x1EA7;n n&#xE0;y gi&#x1ED1;ng nh&#x1B0; search google b&#x1EB1;ng h&#xEC;nh &#x1EA3;nh<br>
Chi ti&#x1EBF;t v&#x1EC1; c&#xE1;c tr&#x1B0;&#x1EDD;ng, c&#xE1;c ki&#x1EC3;u detect v&#xE0; c&#xE1;ch s&#x1EED; d&#x1EE5;ng c&#xE1;c b&#x1EA1;n c&#xF3; th&#x1EC3; &#x111;&#x1ECD;c trong t&#xE0;i li&#x1EC7;u Cloud VisionAPI: <a href="https://cloud.google.com/vision/docs?ref=blog.arrow-tech.vn">https://cloud.google.com/vision/docs</a></li>
</ul>
<p><strong>2.4	T&#x1EA1;o request t&#x1EDB;i Cloud API b&#x1EB1;ng curl</strong></p>
<p>&#x110;&#x1EBF;n ph&#x1EA7;n th&#xFA; v&#x1ECB; nh&#x1EA5;t c&#x1EE7;a Cloud API r&#x1ED3;i.<br>
Sau khi &#x111;&#xE3; t&#x1EA1;o xong file request.json, tr&#xEA;n c&#x1EED;a s&#x1ED5; terminal, b&#x1EA1;n th&#x1EF1;c hi&#x1EC7;n l&#x1EC7;nh:<br>
curl -s -X POST -H &quot;Content-Type: application/json&quot; --data-binary @request.json <a href="https://vision.googleapis.com/v1/images:annotate?key=%24%7BAPI_KEY%7D&amp;ref=blog.arrow-tech.vn">https://vision.googleapis.com/v1/images:annotate?key=${API_KEY}</a><br>
V&#xED; d&#x1EE5; m&#xEC;nh s&#x1EBD; th&#x1EED; detect &#x1EA3;nh sau xem n&#x1ED9;i dung nh&#x1EAD;n &#x111;&#x1B0;&#x1EE3;c l&#xE0; g&#xEC; nh&#xE9;!<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture27.png" alt="Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API" loading="lazy"><br>
N&#x1ED9;i dung file request.json c&#x1EE7;a m&#xEC;nh s&#x1EBD; l&#xE0;:</p>
<pre><code>{
  &quot;requests&quot;:[
    {
      &quot;image&quot;:{
        &quot;source&quot;:{
          &quot;imageUri&quot;:
            &quot;https://znews-photo-td.zadn.vn/w1024/Uploaded/ohunuai/2018_07_19/NGUYEN_BA_NGOC1166_Zing.jpg&quot;
        }
      },
      &quot;features&quot;:[
        {
          &quot;type&quot;:&quot;LABEL_DETECTION&quot;,
          &quot;maxResults&quot;:10
        }
      ]
    }
  ]
}
</code></pre>
<p>V&#xE0; k&#x1EBF;t qu&#x1EA3; tr&#x1EA3; v&#x1EC1;:</p>
<pre><code>{
  &quot;responses&quot;: [
    {
      &quot;labelAnnotations&quot;: [
        {
          &quot;mid&quot;: &quot;/m/088fh&quot;,
          &quot;description&quot;: &quot;yellow&quot;,
          &quot;score&quot;: 0.951962,
          &quot;topicality&quot;: 0.951962
        },
        {
          &quot;mid&quot;: &quot;/m/06z04&quot;,
          &quot;description&quot;: &quot;skin&quot;,
          &quot;score&quot;: 0.9510442,
          &quot;topicality&quot;: 0.9510442
        },
        {
          &quot;mid&quot;: &quot;/m/01k74n&quot;,
          &quot;description&quot;: &quot;facial expression&quot;,
          &quot;score&quot;: 0.9331107,
          &quot;topicality&quot;: 0.9331107
        },
        {
          &quot;mid&quot;: &quot;/m/01f43&quot;,
          &quot;description&quot;: &quot;beauty&quot;,
          &quot;score&quot;: 0.91344154,
          &quot;topicality&quot;: 0.91344154
        },
        {
          &quot;mid&quot;: &quot;/m/05r655&quot;,
          &quot;description&quot;: &quot;girl&quot;,
          &quot;score&quot;: 0.8986084,
          &quot;topicality&quot;: 0.8986084
        },
        {
          &quot;mid&quot;: &quot;/m/02pkb8&quot;,
          &quot;description&quot;: &quot;lady&quot;,
          &quot;score&quot;: 0.8730116,
          &quot;topicality&quot;: 0.8730116
        },
        {
          &quot;mid&quot;: &quot;/m/019nj4&quot;,
          &quot;description&quot;: &quot;smile&quot;,
          &quot;score&quot;: 0.84830636,
          &quot;topicality&quot;: 0.84830636
        },
        {
          &quot;mid&quot;: &quot;/m/06pg22&quot;,
          &quot;description&quot;: &quot;snapshot&quot;,
          &quot;score&quot;: 0.8176745,
          &quot;topicality&quot;: 0.8176745
        },
        {
          &quot;mid&quot;: &quot;/m/015c4z&quot;,
          &quot;description&quot;: &quot;sitting&quot;,
          &quot;score&quot;: 0.81240934,
          &quot;topicality&quot;: 0.81240934
        },
        {
          &quot;mid&quot;: &quot;/m/05wkw&quot;,
          &quot;description&quot;: &quot;photography&quot;,
          &quot;score&quot;: 0.7999211,
          &quot;topicality&quot;: 0.7999211
        }
      ]
    }
  ]
}
</code></pre>
<p>Danh s&#xE1;ch k&#x1EBF;t qu&#x1EA3; tr&#x1EA3; v&#x1EC1; &#x111;&#x1B0;&#x1EE3;c s&#x1EAF;p x&#x1EBF;p theo score gi&#x1EA3;m d&#x1EA7;n. M&#xEC;nh th&#x1EA5;y Google nh&#x1EAD;n d&#x1EA1;ng kh&#xE1; ch&#xED;nh x&#xE1;c.</p>
<p><strong>2.5	T&#x1EA1;o request t&#x1EDB;i Cloud API b&#x1EB1;ng Postman</strong></p>
<p>Ti&#x1EBF;p theo m&#xEC;nh s&#x1EBD; h&#x1B0;&#x1EDB;ng d&#x1EAB;n c&#xE1;c b&#x1EA1;n s&#x1EED; d&#x1EE5;ng Postman &#x111;&#x1EC3; t&#x1EA1;o request detect &#x1EA3;nh.<br>
Cloud Vision API l&#xE0; m&#x1ED9;t REST API v&#x1EDB;i method l&#xE0; POST. Body ch&#xED;nh l&#xE0; n&#x1ED9;i dung c&#x1EE7;a file request.json &#x1EDF; tr&#xEA;n.<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture28.png" alt="Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API" loading="lazy"><br>
(Tr&#xEA;n URL c&#xE1;c b&#x1EA1;n thay xxx b&#x1EB1;ng API Key t&#x1EA1;o &#x1EDF; tr&#xEA;n nh&#xE9;)<br>
Sau &#x111;&#xF3; b&#x1EA1;n nh&#x1EA5;n n&#xFA;t Send v&#xE0; k&#x1EBF;t qu&#x1EA3; b&#x1EA1;n nh&#x1EAD;n &#x111;&#x1B0;&#x1EE3;c:<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture29.png" alt="Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API" loading="lazy"><br>
Google Cloud Vision API l&#xE0; m&#x1ED9;t API n&#xEA;n b&#x1EA1;n ho&#xE0;n to&#xE0;n c&#xF3; th&#x1EC3; s&#x1EED; d&#x1EE5;ng &#x111;&#x1EC3; detect &#x1EA3;nh &#x1EDF; trong app c&#x1EE7;a m&#xEC;nh. &#x1EDE; ph&#x1EA7;n ti&#x1EBF;p theo m&#xEC;nh s&#x1EBD; demo m&#x1ED9;t app android s&#x1EED; d&#x1EE5;ng Google Cloud Vision API &#x111;&#x1EC3; nh&#x1EAD;n d&#x1EA1;ng c&#xE1;c v&#x1EAD;t th&#x1EC3; tr&#xEA;n camera m&#x1ED9;t c&#xE1;ch real-time.</p>
<p><strong>3	App demo</strong></p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture30.png" alt="Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API" loading="lazy"><br>
Trong app n&#xE0;y, c&#x1EE9; 5 gi&#xE2;y m&#xEC;nh l&#x1EA1;i ch&#x1EE5;p &#x1EA3;nh r&#x1ED3;i encode &#x1EA3;nh &#x111;&#xF3; sang base64 r&#x1ED3;i d&#xF9;ng Google Vision API v&#x1EDB;i request &#x1EA3;nh &#x1EDF; d&#x1EA1;ng base64 &#x111;&#x1EC3; l&#x1EA5;y v&#x1EC1; k&#x1EBF;t qu&#x1EA3;.<br>
Source code: <a href="https://github.com/quanghd96/GoogleCloudVision?ref=blog.arrow-tech.vn">https://github.com/quanghd96/GoogleCloudVision</a></p>
<p><strong>4	T&#x1ED5;ng k&#x1EBF;t</strong></p>
<p>V&#x1EAD;y l&#xE0; m&#xEC;nh &#x111;&#xE3; h&#x1B0;&#x1EDB;ng d&#x1EAB;n xong c&#xE1;c b&#x1EA1;n c&#xE1;ch s&#x1EED; d&#x1EE5;ng Google Cloud Vision API &#x111;&#x1EC3; detect &#x1EA3;nh. Hy v&#x1ECD;ng s&#x1EBD; gi&#xFA;p &#xED;ch cho c&#xE1;c b&#x1EA1;n ph&#x1EA7;n n&#xE0;o trong vi&#x1EC7;c h&#x1ECD;c t&#x1EAD;p, ph&#xE1;t tri&#x1EC3;n s&#x1EA3;n ph&#x1EA9;m,&#x2026; C&#x1EA3;m &#x1A1;n c&#xE1;c b&#x1EA1;n &#x111;&#xE3; theo d&#xF5;i b&#xE0;i vi&#x1EBF;t c&#x1EE7;a m&#xEC;nh!<br>
T&#xE0;i li&#x1EC7;u tham kh&#x1EA3;o:</p>
<ul>
<li><a href="https://qwiklabs.com/focuses/1841?parent=catalog&amp;ref=blog.arrow-tech.vn">https://qwiklabs.com/focuses/1841?parent=catalog</a></li>
<li><a href="https://cloud.google.com/vision/docs?ref=blog.arrow-tech.vn">https://cloud.google.com/vision/docs</a></li>
</ul>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Lập trình ứng dụng chat đơn giản trên di động với Flutter]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p><strong>Gi&#x1EDB;i thi&#x1EC7;u &#x1EE9;ng d&#x1EE5;ng</strong></p>
<p>&#x1EE8;ng d&#x1EE5;ng chat gi&#xFA;p m&#x1ECD;i ng&#x1B0;&#x1EDD;i chat nh&#xF3;m realtime, chia s&#x1EBB; h&#xEC;nh &#x1EA3;nh. Tuy nhi&#xEA;n, trong b&#xE0;i vi&#x1EBF;</p>]]></description><link>https://blog.arrow-tech.vn/lap-trinh-ung-dung-chat-don-gian-tren-di-dong-voi-flutter/</link><guid isPermaLink="false">63915acd7a2f410001205db7</guid><category><![CDATA[Flutter]]></category><category><![CDATA[Android]]></category><category><![CDATA[iOS]]></category><dc:creator><![CDATA[Quang Dang]]></dc:creator><pubDate>Wed, 03 Oct 2018 02:52:05 GMT</pubDate><media:content url="https://blog.arrow-tech.vn/content/images/2018/12/flutter_blog-2-750x400.png" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://blog.arrow-tech.vn/content/images/2018/12/flutter_blog-2-750x400.png" alt="L&#x1EAD;p tr&#xEC;nh &#x1EE9;ng d&#x1EE5;ng chat &#x111;&#x1A1;n gi&#x1EA3;n tr&#xEA;n di &#x111;&#x1ED9;ng v&#x1EDB;i Flutter"><p><strong>Gi&#x1EDB;i thi&#x1EC7;u &#x1EE9;ng d&#x1EE5;ng</strong></p>
<p>&#x1EE8;ng d&#x1EE5;ng chat gi&#xFA;p m&#x1ECD;i ng&#x1B0;&#x1EDD;i chat nh&#xF3;m realtime, chia s&#x1EBB; h&#xEC;nh &#x1EA3;nh. Tuy nhi&#xEA;n, trong b&#xE0;i vi&#x1EBF;t n&#xE0;y m&#xEC;nh s&#x1EBD; ch&#x1EC9; h&#x1B0;&#x1EDB;ng d&#x1EAB;n c&#xE1;c b&#x1EA1;n c&#xE1;ch t&#x1EA1;o m&#x1ED9;t &#x1EE9;ng d&#x1EE5;ng chat local. C&#xF2;n c&#xE1;c ch&#x1EE9;c n&#x103;ng &#x111;&#x103;ng nh&#x1EAD;p, chat online realtime, chia s&#x1EBB; h&#xEC;nh &#x1EA3;nh m&#xEC;nh s&#x1EBD; h&#x1B0;&#x1EDB;ng d&#x1EAB;n &#x1EDF; c&#xE1;c b&#xE0;i vi&#x1EBF;t ti&#x1EBF;p theo.</p>
<p><strong>C&#xE0;i &#x111;&#x1EB7;t m&#xF4;i tr&#x1B0;&#x1EDD;ng</strong></p>
<p>&#x110;&#x1EC3; b&#x1EAF;t &#x111;&#x1EA7;u, b&#x1EA1;n c&#x1EA7;n c&#xE0;i &#x111;&#x1EB7;t Flutter SDK v&#xE0; m&#x1ED9;t editor c&#xF3; c&#xE0;i s&#x1EB5;n plugin Flutter (trong b&#xE0;i vi&#x1EBF;t n&#xE0;y m&#xEC;nh s&#x1EED; d&#x1EE5;ng IntelliJ v&#xEC; n&#xF3; r&#x1EA5;t ti&#x1EC7;n l&#x1EE3;i v&#xE0; th&#xF4;ng minh). Vi&#x1EC7;c c&#xE0;i &#x111;&#x1EB7;t Flutter SDK b&#x1EA1;n c&#xF3; th&#x1EC3; tham kh&#x1EA3;o &#x1EDF; &#x111;&#x1B0;&#x1EDD;ng link sau: <a href="https://flutter.io/get-started/install/?ref=blog.arrow-tech.vn">https://flutter.io/get-started/install/</a></p>
<p>Ngo&#xE0;i ra b&#x1EA1;n c&#x1EA7;n th&#xEA;m m&#x1ED9;t thi&#x1EBF;t b&#x1ECB; th&#x1EAD;t ho&#x1EB7;c m&#xE1;y &#x1EA3;o (Android ho&#x1EB7;c iOS) &#x111;&#x1EC3; test.</p>
<p><strong>T&#x1EA1;o project</strong></p>
<p>B&#x1EA1;n m&#x1EDF; IntelliJ, ch&#x1ECD;n Create New Project, sau &#x111;&#xF3; ch&#x1ECD;n Flutter nh&#x1B0; h&#xEC;nh d&#x1B0;&#x1EDB;i:</p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture1.png" alt="L&#x1EAD;p tr&#xEC;nh &#x1EE9;ng d&#x1EE5;ng chat &#x111;&#x1A1;n gi&#x1EA3;n tr&#xEA;n di &#x111;&#x1ED9;ng v&#x1EDB;i Flutter" loading="lazy"></p>
<p>N&#x1EBF;u Flutter SDK Path b&#x1ECB; tr&#x1ED1;ng th&#xEC; b&#x1EA1;n tr&#x1ECF; &#x111;&#x1B0;&#x1EDD;ng d&#x1EAB;n t&#x1EDB;i th&#x1B0; m&#x1EE5;c ch&#x1EE9;a Flutter nh&#xE9;. Sau &#x111;&#xF3; nh&#x1EA5;n Next. C&#xE1;c b&#x1EA1;n c&#xF3; th&#x1EC3; thay &#x111;&#x1ED5;i th&#xF4;ng tin project ho&#x1EB7;c &#x111;&#x1EC3; m&#x1EB7;c &#x111;&#x1ECB;nh. Cu&#x1ED1;i c&#xF9;ng nh&#x1EA5;n Finish. Nh&#x1B0; v&#x1EAD;y l&#xE0; c&#xE1;c b&#x1EA1;n &#x111;&#xE3; t&#x1EA1;o th&#xE0;nh c&#xF4;ng &#x1EE9;ng d&#x1EE5;ng s&#x1EED; d&#x1EE5;ng Flutter.</p>
<p>D&#x1B0;&#x1EDB;i &#x111;&#xE2;y l&#xE0; h&#xEC;nh &#x1EA3;nh to&#xE0;n b&#x1ED9; project sau khi &#x111;&#xE3; t&#x1EA1;o xong.</p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture2.png" alt="L&#x1EAD;p tr&#xEC;nh &#x1EE9;ng d&#x1EE5;ng chat &#x111;&#x1A1;n gi&#x1EA3;n tr&#xEA;n di &#x111;&#x1ED9;ng v&#x1EDB;i Flutter" loading="lazy"></p>
<p>Th&#x1B0; m&#x1EE5;c lib ch&#x1EE9;a to&#xE0;n b&#x1ED9; source code c&#x1EE7;a project. Hi&#x1EC7;n t&#x1EA1;i c&#xE1;c b&#x1EA1;n ch&#x1EC9; c&#x1EA7;n quan t&#xE2;m &#x111;&#x1EBF;n th&#x1B0; m&#x1EE5;c n&#xE0;y. &#x110;&#x1EC3; ch&#x1EA1;y th&#x1EED; c&#xE1;c b&#x1EA1;n nh&#x1EA5;n v&#xE0;o n&#xFA;t Run tr&#xEA;n thanh c&#xF4;ng c&#x1EE5;.</p>
<p>M&#x1ED9;t t&#xED;nh n&#x103;ng r&#x1EA5;t th&#xFA; v&#x1ECB; c&#x1EE7;a Flutter l&#xE0; Hot reload. &#x110;&#xF3; l&#xE0; khi b&#x1EA1;n s&#x1EED;a code v&#xE0; l&#x1B0;u l&#x1EA1;i, &#x1EE9;ng d&#x1EE5;ng s&#x1EBD; &#x111;&#x1B0;&#x1EE3;c reload m&#xE0; b&#x1EA1;n kh&#xF4;ng c&#x1EA7;n ph&#x1EA3;i build l&#x1EA1;i. B&#x1EA1;n c&#xF3; th&#x1EC3; tr&#x1EA3;i nghi&#x1EC7;m ngay t&#xED;nh n&#x103;ng n&#xE0;y b&#x1EB1;ng c&#xE1;ch tr&#xEA;n file main.dart, b&#x1EA1;n s&#x1EED;a primarySwatch: Colors.blue th&#xE0;nh primarySwatch: Colors.red sau &#x111;&#xF3; l&#x1B0;u l&#x1EA1;i. &#x1EE8;ng d&#x1EE5;ng s&#x1EBD; t&#x1EF1; &#x111;&#x1ED9;ng chuy&#x1EC3;n giao di&#x1EC7;n t&#x1EEB; m&#xE0;u xanh sang m&#xE0;u &#x111;&#x1ECF;. R&#x1EA5;t th&#xFA; v&#x1ECB; ph&#x1EA3;i kh&#xF4;ng?</p>
<p>Sau &#x111;&#xE2;y ch&#xFA;ng ta s&#x1EBD; ti&#x1EBF;n h&#xE0;nh t&#x1EA1;o giao di&#x1EC7;n cho &#x1EE9;ng d&#x1EE5;ng chat.</p>
<p><strong>T&#x1EA1;o giao di&#x1EC7;n</strong></p>
<p>Ch&#xFA;ng ta c&#x1EA7;n t&#x1EA1;o giao di&#x1EC7;n g&#x1ED3;m:</p>
<ul>
<li>M&#x1ED9;t list &#x111;&#x1EC3; hi&#x1EC3;n th&#x1ECB; tin nh&#x1EAF;n</li>
<li>M&#x1ED9;t &#xF4; &#x111;&#x1EC3; nh&#x1EAD;p tin nh&#x1EAF;n</li>
<li>M&#x1ED9;t n&#xFA;t &#x111;&#x1EC3; g&#x1EED;i tin nh&#x1EAF;n</li>
</ul>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture3.png" alt="L&#x1EAD;p tr&#xEC;nh &#x1EE9;ng d&#x1EE5;ng chat &#x111;&#x1A1;n gi&#x1EA3;n tr&#xEA;n di &#x111;&#x1ED9;ng v&#x1EDB;i Flutter" loading="lazy"></p>
<p>Sau &#x111;&#xE2;y ch&#xFA;ng ta s&#x1EBD; t&#x1EA1;o l&#x1EA7;n l&#x1B0;&#x1EE3;t t&#x1EEB;ng &#x111;&#x1ED1;i t&#x1B0;&#x1EE3;ng tr&#xEA;n v&#xE0; gh&#xE9;p ch&#xFA;ng l&#x1EA1;i th&#xE0;nh m&#x1ED9;t &#x1EE9;ng d&#x1EE5;ng ho&#xE0;n ch&#x1EC9;nh ch&#x1EA1;y tr&#xEA;n thi&#x1EBF;t b&#x1ECB; th&#x1EAD;t.</p>
<p><strong>T&#x1EA1;o giao di&#x1EC7;n c&#x1A1; b&#x1EA3;n cho &#x1EE9;ng d&#x1EE5;ng</strong></p>
<p>Khi t&#x1EA1;o m&#x1EDB;i m&#x1ED9;t project, trong &#x111;&#xF3; &#x111;&#xE3; c&#xF3; s&#x1EB5;n m&#x1ED9;t s&#x1ED1; th&#xE0;nh ph&#x1EA7;n. Ch&#xFA;ng ta c&#x1EA7;n x&#xF3;a &#x111;i nh&#x1EEF;ng th&#x1EE9; kh&#xF4;ng li&#xEA;n quan &#x111;&#x1EBF;n &#x1EE9;ng d&#x1EE5;ng chat. B&#x1EA1;n s&#x1EED;a l&#x1EA1;i class _MyHomePageState nh&#x1B0; h&#xEC;nh d&#x1B0;&#x1EDB;i &#x111;&#xE2;y.</p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture4.png" alt="L&#x1EAD;p tr&#xEC;nh &#x1EE9;ng d&#x1EE5;ng chat &#x111;&#x1A1;n gi&#x1EA3;n tr&#xEA;n di &#x111;&#x1ED9;ng v&#x1EDB;i Flutter" loading="lazy"></p>
<p>V&#xE0; &#x111;&#xE2;y l&#xE0; h&#xEC;nh &#x1EA3;nh &#x1EE9;ng d&#x1EE5;ng tr&#x1EAF;ng ch&#x1B0;a c&#xF3; g&#xEC;. Ch&#xFA;ng ta c&#x1EA7;n ph&#x1EA3;i x&#xE2;y d&#x1EF1;ng c&#xE1;c th&#xE0;nh ph&#x1EA7;n &#x111;&#xE3; &#x111;&#x1B0;&#x1EE3;c li&#x1EC7;t k&#xEA; &#x1EDF; tr&#xEA;n.</p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture5.png" alt="L&#x1EAD;p tr&#xEC;nh &#x1EE9;ng d&#x1EE5;ng chat &#x111;&#x1A1;n gi&#x1EA3;n tr&#xEA;n di &#x111;&#x1ED9;ng v&#x1EDB;i Flutter" loading="lazy"></p>
<p><strong>T&#x1EA1;o &#xF4; &#x111;&#x1EC3; nh&#x1EAD;p tin nh&#x1EAF;n</strong></p>
<p>&#x110;&#x1EC3; t&#x1EA1;o &#xF4; nh&#x1EAD;p tin nh&#x1EAF;n, b&#x1EA1;n t&#x1EA1;o h&#xE0;m sau &#x111;&#xE2;y b&#xEA;n trong class _MyHomePageState:</p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture6.png" alt="L&#x1EAD;p tr&#xEC;nh &#x1EE9;ng d&#x1EE5;ng chat &#x111;&#x1A1;n gi&#x1EA3;n tr&#xEA;n di &#x111;&#x1ED9;ng v&#x1EDB;i Flutter" loading="lazy"></p>
<p>M&#xEC;nh s&#x1EBD; gi&#x1EA3;i th&#xED;ch qua v&#x1EC1; h&#xE0;m n&#xE0;y:</p>
<p>H&#xE0;m n&#xE0;y s&#x1EBD; tr&#x1EA3; v&#x1EC1; cho ch&#xFA;ng ta m&#x1ED9;t widget g&#x1ED3;m m&#x1ED9;t TextField (l&#xE0; &#xF4; ch&#xFA;ng ta nh&#x1EAD;p tin nh&#x1EAF;n) v&#x1EDB;i c&#xE1;c &#x111;&#x1ECB;nh d&#x1EA1;ng giao di&#x1EC7;n c&#x1EE7;a n&#xF3;. B&#x1EA1;n c&#xF3; th&#x1EC3; thay &#x111;&#x1ED5;i m&#x1ED9;t s&#x1ED1; th&#xF4;ng s&#x1ED1; v&#xE0; xem s&#x1EF1; thay &#x111;&#x1ED5;i tr&#xEA;n app.</p>
<p>controller l&#xE0; th&#xE0;nh ph&#x1EA7;n qu&#x1EA3;n l&#xFD; TextField nh&#x1B0; vi&#x1EC7;c l&#x1EA5;y tin nh&#x1EAF;n, x&#xF3;a tin nh&#x1EAF;n,... tr&#xEA;n TextField</p>
<p>onSubmitted l&#xE0; th&#xE0;nh ph&#x1EA7;n x&#x1EED; l&#xFD; khi ng&#x1B0;&#x1EDD;i d&#xF9;ng submit tin nh&#x1EAF;n</p>
<p>decoration l&#xE0; th&#xE0;nh ph&#x1EA7;n gi&#xFA;p &#x111;&#x1ECB;nh d&#x1EA1;ng cho TextField nh&#x1B0; text hint,&#x2026;</p>
<p>Ti&#x1EBF;p theo b&#x1EA1;n c&#x1EA7;n t&#x1EA1;o &#x111;&#x1ED1;i t&#x1B0;&#x1EE3;ng _textController &#x111;&#x1EC3; qu&#x1EA3;n l&#xFD; TextField</p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture7.png" alt="L&#x1EAD;p tr&#xEC;nh &#x1EE9;ng d&#x1EE5;ng chat &#x111;&#x1A1;n gi&#x1EA3;n tr&#xEA;n di &#x111;&#x1ED9;ng v&#x1EDB;i Flutter" loading="lazy"></p>
<p>T&#x1EA1;o h&#xE0;m _handleSubmitted &#x111;&#x1EC3; x&#x1EED; l&#xFD; khi ng&#x1B0;&#x1EDD;i d&#xF9;ng submit:</p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture8.png" alt="L&#x1EAD;p tr&#xEC;nh &#x1EE9;ng d&#x1EE5;ng chat &#x111;&#x1A1;n gi&#x1EA3;n tr&#xEA;n di &#x111;&#x1ED9;ng v&#x1EDB;i Flutter" loading="lazy"></p>
<p>H&#xE0;m n&#xE0;y s&#x1EBD; nh&#x1EAD;n v&#xE0;o tin nh&#x1EAF;n sau &#x111;&#xF3; x&#x1EED; l&#xFD;. T&#x1EA1;m th&#x1EDD;i ch&#xFA;ng ta s&#x1EBD; th&#x1EF1;c hi&#x1EC7;n vi&#x1EC7;c x&#xF3;a tin nh&#x1EAF;n tr&#xEA;n &#xF4; TextField</p>
<p>Nh&#x1B0; v&#x1EAD;y vi&#x1EC7;c t&#x1EA1;o &#xF4; nh&#x1EAD;p tin nh&#x1EAF;n &#x111;&#xE3; ho&#xE0;n th&#xE0;nh. Ti&#x1EBF;p theo ch&#xFA;ng ta s&#x1EBD; t&#x1EA1;o n&#xFA;t g&#x1EED;i tin nh&#x1EAF;n.</p>
<p><strong>T&#x1EA1;o n&#xFA;t g&#x1EED;i tin nh&#x1EAF;n</strong></p>
<p>Ch&#xFA;ng ta s&#x1EBD; vi&#x1EBF;t l&#x1EA1;i h&#xE0;m _buildTextComposer nh&#x1B0; sau:</p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture9.png" alt="L&#x1EAD;p tr&#xEC;nh &#x1EE9;ng d&#x1EE5;ng chat &#x111;&#x1A1;n gi&#x1EA3;n tr&#xEA;n di &#x111;&#x1ED9;ng v&#x1EDB;i Flutter" loading="lazy"></p>
<p>B&#x1EA1;n th&#x1EA5;y h&#xE0;m c&#x1EE7;a ch&#xFA;ng ta &#x111;&#xE3; ph&#x1EE9;c t&#x1EA1;p h&#x1A1;n r&#x1EA5;t nhi&#x1EC1;u r&#x1ED3;i &#x111;&#xFA;ng kh&#xF4;ng?</p>
<p>Nh&#x1B0;ng s&#x1EBD; r&#x1EA5;t d&#x1EC5; hi&#x1EC3;u th&#xF4;i, IconTheme ch&#xFA;ng l&#xE0; Widget m&#xE0; gi&#xFA;p c&#xE1;c ph&#x1EA7;n t&#x1EED; b&#xEA;n trong n&#xF3; nh&#x1B0; n&#xFA;t g&#x1EED;i tin nh&#x1EAF;n c&#x1EE7;a ch&#xFA;ng ta hi&#x1EC3;n th&#x1ECB; m&#xE0;u theo theme hi&#x1EC7;n t&#x1EA1;i.</p>
<p>Do ch&#xFA;ng ta t&#x1EA1;o th&#xEA;m m&#x1ED9;t n&#xFA;t n&#x1EEF;a n&#xEA;n c&#x1EA7;n ph&#x1EA3;i &#x111;&#x1B0;a ch&#xFA;ng v&#xE0;o 1 Row (row s&#x1EBD; hi&#x1EC3;n th&#x1ECB; c&#xE1;c ph&#x1EA7;n t&#x1EED; theo chi&#x1EC1;u ngang).</p>
<p>TextField &#x111;&#x1B0;&#x1EE3;c &#x111;&#x1B0;a v&#xE0;o b&#xEA;n trong widget Flexible &#x111;&#x1EC3; l&#xFA;c n&#xE0;o chi&#x1EC1;u d&#xE0;i c&#x1EE7;a n&#xF3; c&#x169;ng k&#xED;n m&#xE0;n h&#xEC;nh.</p>
<p>N&#xFA;t g&#x1EED;i ch&#xFA;ng ta s&#x1EBD; s&#x1EED; d&#x1EE5;ng Widget IconButton v&#x1EDB;i:</p>
<p>icon l&#xE0; icon c&#x1EE7;a n&#xFA;t</p>
<p>onPressed l&#xE0; s&#x1EF1; ki&#x1EC7;n nh&#x1EA5;n n&#xFA;t. Ch&#xFA;ng ta s&#x1EBD; x&#x1EED; l&#xFD; trong h&#xE0;m _handleSubmitted &#x1EDF; tr&#xEA;n v&#x1EDB;i tham s&#x1ED1; truy&#x1EC1;n v&#xE0;o l&#xE0; tin nh&#x1EAF;n l&#x1EA5;y t&#x1EEB; &#x111;&#x1ED1;i t&#x1B0;&#x1EE3;ng _textController &#x1EDF; tr&#xEA;n.</p>
<p>Nh&#x1B0; v&#x1EAD;y l&#xE0; &#x111;&#xE3; xong. Ch&#xFA;ng ta l&#xE0;m ph&#x1EA7;n cu&#x1ED1;i c&#xF9;ng l&#xE0; list tin nh&#x1EAF;n.</p>
<p><strong>T&#x1EA1;o list hi&#x1EC3;n th&#x1ECB; tin nh&#x1EAF;n</strong></p>
<p>&#x110;&#x1EA7;u ti&#xEA;n ch&#xFA;ng ta s&#x1EBD; t&#x1EA1;o ra widget &#x111;&#x1EC3; hi&#x1EC3;n th&#x1ECB; 1 tin nh&#x1EAF;n</p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture10.png" alt="L&#x1EAD;p tr&#xEC;nh &#x1EE9;ng d&#x1EE5;ng chat &#x111;&#x1A1;n gi&#x1EA3;n tr&#xEA;n di &#x111;&#x1ED9;ng v&#x1EDB;i Flutter" loading="lazy"></p>
<p>Widget n&#xE0;y s&#x1EBD; g&#x1ED3;m c&#xF3; 1 icon l&#xE0; avatar c&#x1EE7;a ng&#x1B0;&#x1EDD;i g&#x1EED;i v&#xE0; b&#xEA;n c&#x1EA1;nh l&#xE0; m&#x1ED9;t Text &#x111;&#x1EC3; hi&#x1EC3;n th&#x1ECB; tin nh&#x1EAF;n c&#x1EE7;a ng&#x1B0;&#x1EDD;i &#x111;&#xF3;.</p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture11.png" alt="L&#x1EAD;p tr&#xEC;nh &#x1EE9;ng d&#x1EE5;ng chat &#x111;&#x1A1;n gi&#x1EA3;n tr&#xEA;n di &#x111;&#x1ED9;ng v&#x1EDB;i Flutter" loading="lazy"></p>
<p>Sau &#x111;&#xF3; ch&#xFA;ng ta s&#x1EBD; t&#x1EA1;o ra list ch&#x1EE9;a c&#xE1;c ChatMessage tr&#xEA;n:</p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture12.png" alt="L&#x1EAD;p tr&#xEC;nh &#x1EE9;ng d&#x1EE5;ng chat &#x111;&#x1A1;n gi&#x1EA3;n tr&#xEA;n di &#x111;&#x1ED9;ng v&#x1EDB;i Flutter" loading="lazy"></p>
<p>Ch&#xFA;ng ta s&#x1EBD; s&#x1EED; d&#x1EE5;ng ListView v&#x1EDB;i:</p>
<p>itemBuilder l&#xE0; th&#xE0;nh ph&#x1EA7;n build ra t&#x1EEB;ng d&#xF2;ng tin nh&#x1EAF;n</p>
<p>itemCount l&#xE0; s&#x1ED1; l&#x1B0;&#x1EE3;ng tin nh&#x1EAF;n hi&#x1EC3;n th&#x1ECB; tr&#xEA;n list</p>
<p>&#x1EDE; &#x111;&#xE2;y ch&#xFA;ng ta c&#x1EA7;n t&#x1EA1;o ra m&#x1ED9;t bi&#x1EBF;n _messages ch&#x1EE9;a c&#xE1;c ChatMessage:</p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture13.png" alt="L&#x1EAD;p tr&#xEC;nh &#x1EE9;ng d&#x1EE5;ng chat &#x111;&#x1A1;n gi&#x1EA3;n tr&#xEA;n di &#x111;&#x1ED9;ng v&#x1EDB;i Flutter" loading="lazy"></p>
<p>Khi l&#x1B0;u l&#x1EA1;i b&#x1EA1;n s&#x1EBD; th&#x1EA5;y &#xF4; nh&#x1EAD;p tin nh&#x1EAF;n v&#xE0; n&#xFA;t g&#x1EED;i &#x111;&#xE3; &#x111;&#x1B0;&#x1EE3;c di chuy&#x1EC3;n xu&#x1ED1;ng ph&#xED;a d&#x1B0;&#x1EDB;i m&#xE0;n h&#xEC;nh. &#x110;&#xF3; ch&#xED;nh l&#xE0; do widget Flexiable.</p>
<p>Cu&#x1ED1;i c&#xF9;ng ch&#xFA;ng ta c&#x1EA7;n x&#x1EED; l&#xFD; khi ng&#x1B0;&#x1EDD;i d&#xF9;ng nh&#x1EA5;n n&#xFA;t g&#x1EED;i s&#x1EBD; hi&#x1EC3;n th&#x1ECB; tin nh&#x1EAF;n &#x111;&#xF3; v&#xE0;o list trong h&#xE0;m _handleSubmitted nh&#x1B0; sau:</p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture14.png" alt="L&#x1EAD;p tr&#xEC;nh &#x1EE9;ng d&#x1EE5;ng chat &#x111;&#x1A1;n gi&#x1EA3;n tr&#xEA;n di &#x111;&#x1ED9;ng v&#x1EDB;i Flutter" loading="lazy"></p>
<p>H&#xE0;m setState tr&#xEA;n s&#x1EBD; set l&#x1EA1;i bi&#x1EBF;n _messages v&#xE0; c&#x1EAD;p nh&#x1EAD;t l&#x1EA1;i giao di&#x1EC7;n m&#x1ED9;t c&#xE1;ch realtime. &#x110;&#xE2;y c&#x169;ng ch&#xED;nh l&#xE0; m&#x1ED9;t t&#xED;nh n&#x103;ng r&#x1EA5;t hay c&#x1EE7;a Flutter. N&#x1EBF;u b&#x1EA1;n n&#xE0;o &#x111;&#xE3; t&#x1EEB;ng bi&#x1EBF;t React Native th&#xEC; ch&#x1EAF;c h&#x1EB3;n s&#x1EBD; r&#x1EA5;t quen thu&#x1ED9;c v&#x1EDB;i state v&#xE0; h&#xE0;m n&#xE0;y.</p>
<p>Nh&#x1B0; v&#x1EAD;y &#x111;&#xE3; xong.</p>
<p>Source code: <a href="https://github.com/quanghd96/chat_flutter?ref=blog.arrow-tech.vn">https://github.com/quanghd96/chat_flutter</a></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Unity cho người bắt đầu : Cấu trúc thư mục và source code]]></title><description><![CDATA[Bạn đã tự hỏi tại sao cần tới một cấu trúc tốt ngay từ đầu cho một project? Với một cấu trúc tốt bạn càng thực hiện nó tốt nó sẽ giúp bạn tiết kiệm thời gian. Việc xây dựng nhiều dự án trên cùng một nền tảng được thiết kế tốt cũng giúp việc trao đổi giữa các dự án một cách dễ dàng hơn.]]></description><link>https://blog.arrow-tech.vn/unity-cho-nguoi-bat-dau/</link><guid isPermaLink="false">63915acd7a2f410001205db6</guid><category><![CDATA[Unity]]></category><dc:creator><![CDATA[phont]]></dc:creator><pubDate>Mon, 10 Sep 2018 08:03:30 GMT</pubDate><media:content url="https://blog.arrow-tech.vn/content/images/2018/09/unity-folder-git-version-1170x345.png" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><h2 id="1tngquan">1. T&#x1ED5;ng quan</h2>
<img src="https://blog.arrow-tech.vn/content/images/2018/09/unity-folder-git-version-1170x345.png" alt="Unity cho ng&#x1B0;&#x1EDD;i b&#x1EAF;t &#x111;&#x1EA7;u : C&#x1EA5;u tr&#xFA;c th&#x1B0; m&#x1EE5;c v&#xE0; source code"><p>B&#x1EA1;n &#x111;&#xE3; t&#x1EF1; h&#x1ECF;i t&#x1EA1;i sao c&#x1EA7;n t&#x1EDB;i m&#x1ED9;t c&#x1EA5;u tr&#xFA;c t&#x1ED1;t ngay t&#x1EEB; &#x111;&#x1EA7;u cho m&#x1ED9;t project? V&#x1EDB;i m&#x1ED9;t c&#x1EA5;u tr&#xFA;c t&#x1ED1;t b&#x1EA1;n c&#xE0;ng th&#x1EF1;c hi&#x1EC7;n n&#xF3; t&#x1ED1;t n&#xF3; s&#x1EBD; gi&#xFA;p b&#x1EA1;n ti&#x1EBF;t ki&#x1EC7;m th&#x1EDD;i gian. Vi&#x1EC7;c x&#xE2;y d&#x1EF1;ng nhi&#x1EC1;u d&#x1EF1; &#xE1;n tr&#xEA;n c&#xF9;ng m&#x1ED9;t n&#x1EC1;n t&#x1EA3;ng &#x111;&#x1B0;&#x1EE3;c thi&#x1EBF;t k&#x1EBF; t&#x1ED1;t c&#x169;ng gi&#xFA;p vi&#x1EC7;c trao &#x111;&#x1ED5;i gi&#x1EEF;a c&#xE1;c d&#x1EF1; &#xE1;n m&#x1ED9;t c&#xE1;ch d&#x1EC5; d&#xE0;ng h&#x1A1;n. Nh&#x1B0;ng c&#xF3; l&#x1EBD; l&#xFD; do thuy&#x1EBF;t ph&#x1EE5;c nh&#x1EA5;t cho m&#x1ED9;t d&#x1EF1; &#xE1;n c&#xF3; c&#x1EA5;u tr&#xFA;c t&#x1ED1;t ngay t&#x1EEB; &#x111;&#x1EA7;u l&#xE0; vi&#x1EC7;c th&#x1EF1;c thi n&#xF3; s&#x1EBD; d&#x1EC5; d&#xE0;ng h&#x1A1;n.</p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/09/arreveriecodeplanning.png" alt="Unity cho ng&#x1B0;&#x1EDD;i b&#x1EAF;t &#x111;&#x1EA7;u : C&#x1EA5;u tr&#xFA;c th&#x1B0; m&#x1EE5;c v&#xE0; source code" loading="lazy"></p>
<p>Khi ph&#x1EA7;n m&#x1EC1;m, &#x1EE9;ng d&#x1EE5;ng tr&#x1EDF; n&#xEA;n l&#x1EDB;n v&#xE0; ph&#x1EE9;c t&#x1EA1;p th&#xEC; vi&#x1EC7;c duy tr&#xEC; s&#x1EBD; c&#xE0;ng ng&#xE0;y c&#xE0;ng kh&#xF3; kh&#x103;n. &#x110;&#x1EC3; kh&#xF4;ng l&#xE3;ng ph&#xED; th&#x1EDD;i gian v&#xE0;o vi&#x1EC7;c qu&#x1EA3;n l&#xFD; m&#x1ED9;t m&#x1EDB; h&#x1ED7;n &#x111;&#x1ED9;n h&#x1A1;n v&#xE0; vi&#x1EC7;c t&#x1EAD;p trung v&#xE0;o c&#xE1;c t&#xED;nh n&#x103;ng th&#xEC; b&#x1EA1;n c&#x1EA7;n c&#xF3; m&#x1ED9;t c&#x1EA5;u tr&#xFA;c t&#x1ED1;t v&#xE0; gi&#x1EEF; cho n&#xF3; c&#xF3; c&#x1EA5;u tr&#xFA;c t&#x1ED1;t ngay t&#x1EEB; &#x111;&#x1EA7;u. &#x110;&#xE2;y l&#xE0; m&#x1ED9;t t&#x1EAD;p h&#x1EE3;p c&#xE1;c ph&#x1B0;&#x1A1;ng ph&#xE1;p t&#x1ED1;t nh&#x1EA5;t m&#xE0; ch&#xFA;ng t&#xF4;i &#x111;&#xE3; &#x111;&#xFA;c r&#xFA;t qua qu&#xE1; tr&#xEC;nh tr&#x1EA3;i nghi&#x1EC7;m v&#xE0; t&#x1ED5;ng k&#x1EBF;t t&#x1EEB; m&#x1ED9;t s&#x1ED1; trang web kh&#xE1;c.</p>
<h2 id="2phngphp">2. Ph&#x1B0;&#x1A1;ng ph&#xE1;p</h2>
<p>2.1. <strong>Tr&#xE1;nh ph&#xE2;n t&#xE1;ch c&#xE1;c asset</strong>. Ch&#x1EC9; c&#xF3; m&#x1ED9;t phi&#xEA;n b&#x1EA3;n duy nh&#x1EA5;t c&#x1EE7;a b&#x1EA5;t k&#x1EF3; asset n&#xE0;o. N&#x1EBF;u b&#x1EA1;n c&#x1EA7;n thi&#x1EBF;t ph&#xE2;n t&#xE1;ch prefab, scence ho&#x1EB7;c mesh h&#xE3;y l&#xE0;m theo m&#x1ED9;t quy tr&#xEC;nh r&#xF5; r&#xE0;ng cho c&#xE1;c phi&#xEA;n b&#x1EA3;n. C&#xE1;c nh&#xE1;nh &quot;sai&quot; ph&#x1EA3;i &#x111;&#x1B0;&#x1EE3;c l&#xE0;m n&#x1ED5;i b&#x1EAD;t b&#x1EB1;ng c&#xE1;ch &#x111;&#x1EB7;t t&#xEA;n, v&#xED; d&#x1EE5;: s&#x1EED; d&#x1EE5;ng ti&#x1EC1;n t&#x1ED1; d&#x1EA5;u g&#x1EA1;ch d&#x1B0;&#x1EDB;i: _MainSence_Backup</p>
<p>2.2. <strong>S&#x1EED; d&#x1EE5;ng c&#xF4;ng c&#x1EE5; qu&#x1EA3;n l&#xFD; phi&#xEA;n b&#x1EA3;n</strong> cho vi&#x1EC7;c qu&#x1EA3;n l&#xFD; project.<br>
2.3. <strong>C&#x1ED1; g&#x1EAF;ng gi&#x1EEF; cho m&#x1ECD;i th&#x1EE9; ng&#x1EAF;n g&#x1ECD;n v&#xE0; &#x111;&#x1A1;n gi&#x1EA3;n</strong>. C&#x1ED1; g&#x1EAF;ng gi&#x1EEF; cho c&#xE1;c class c&#x1EE7;a b&#x1EA1;n ng&#x1EAF;n g&#x1ECD;n v&#xE0; r&#xF5; r&#xE0;ng. M&#x1ED9;t class nh&#x1ECF; n&#xEA;n c&#xF3; &#xED;t h&#x1A1;n 100 d&#xF2;ng. V&#xE0; c&#xE1;c main class ng&#x103;n h&#x1A1;n 1000 d&#xF2;ng. N&#x1EBF;u v&#x1B0;&#x1EE3;t qua con s&#x1ED1; n&#xE0;y th&#xEC; b&#x1EA1;n &#x111;ang t&#x1EA1;o ra m&#x1ED9;t script t&#x1ED3;i t&#x1EC7; v&#xE0; ch&#xFA;ng ta c&#x1EA7;n ph&#x1EA3;i tr&#xE1;nh &#x111;i&#x1EC1;u &#x111;&#xF3;.</p>
<h2 id="3cutrcthmcvscence">3. C&#x1EA5;u tr&#xFA;c th&#x1B0; m&#x1EE5;c v&#xE0; Scence</h2>
<p>C&#x1EA5;u tr&#xFA;c th&#x1B0; m&#x1EE5;c gi&#xFA;p c&#xE1;c th&#xE0;nh vi&#xEA;n trong nh&#xF3;m c&#x1EE7;a b&#x1EA1;n s&#x1EED;a &#x111;&#x1ED5;i, t&#xEC;m ki&#x1EBF;m, t&#x1ED5; ch&#x1EE9;c project v&#xE0; c&#xE1;c t&#xE0;i nguy&#xEA;n m&#x1ED9;t c&#xE1;ch d&#x1EC5; d&#xE0;ng v&#xE0; &#x111;&#x1ED3;ng th&#x1EDD;i. C&#xF3; r&#x1EA5;t nhi&#x1EC1;u c&#xE1;ch &#x111;&#x1EC3; l&#xE0;m &#x111;i&#x1EC1;u n&#xE0;y, v&#xE0; ch&#xFA;ng t&#xF4;i s&#x1EBD; &#x111;&#x1B0;a ra m&#x1ED9;t s&#x1ED1; v&#xED; d&#x1EE5; c&#x1EE5; th&#x1EC3; m&#xE0; ch&#xFA;ng t&#xF4;i th&#x1EA5;y l&#xE0; ho&#x1EA1;t &#x111;&#x1ED9;ng t&#x1ED1;t. N&#x1EBF;u b&#x1ED1; c&#x1EE5;c d&#x1EF1; &#xE1;n c&#x1EE7;a b&#x1EA1;n &#x111;&#xE1;p &#x1EE9;ng nh&#x1EEF;ng v&#x1EA5;n &#x111;&#x1EC1; sau, th&#xEC; n&#xF3; c&#xF3; th&#x1EC3; l&#xE0; m&#x1ED9;t b&#x1ED1; c&#x1EE5;c kh&#xE1; t&#x1ED1;t.</p>
<ul>
<li>Ai l&#xE0;m n&#xF3;?</li>
<li>N&#xF3; thu&#x1ED9;c lo&#x1EA1;i n&#xE0;o? Script, Audio, Art, Design?</li>
<li>Ph&#x1EA1;m vi c&#x1EE7;a project bao g&#x1ED3;m nh&#x1EEF;ng g&#xEC;?</li>
<li>Gi&#xE1; tr&#x1ECB; c&#x1EE7;a asset v&#xE0; nh&#x1EEF;ng d&#x1EEF; li&#x1EC7;u n&#xE0;o b&#x1EA1;n c&#x1EA7;n quan t&#xE2;m n&#x1EBF;u b&#x1EA1;n thay &#x111;&#x1ED5;i n&#xF3;?</li>
</ul>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/09/UnityFolderStructure.png" alt="Unity cho ng&#x1B0;&#x1EDD;i b&#x1EAF;t &#x111;&#x1EA7;u : C&#x1EA5;u tr&#xFA;c th&#x1B0; m&#x1EE5;c v&#xE0; source code" loading="lazy"></p>
<h2 id="4streamingassets">4. Streaming Assets:</h2>
<p>H&#x1EA7;u h&#x1EBF;t c&#xE1;c asset trong Unity &#x111;&#x1B0;&#x1EE3;c k&#x1EBF;t h&#x1EE3;p v&#xE0;o project khi n&#xF3; &#x111;&#x1B0;&#x1EE3;c x&#xE2;y d&#x1EF1;ng. Tuy nhi&#xEA;n, &#x111;&#xF4;i khi r&#x1EA5;t h&#x1EEF;u &#xED;ch khi &#x111;&#x1EB7;t c&#xE1;c t&#x1EC7;p n&#xE0;y v&#xE0;o h&#x1EC7; th&#x1ED1;ng t&#x1EC7;p b&#xEC;nh th&#x1B0;&#x1EDD;ng tr&#xEA;n m&#xE1;y &#x111;&#xED;ch &#x111;&#x1EC3; l&#xE0;m cho ch&#xFA;ng c&#xF3; th&#x1EC3; truy c&#x1EAD;p qua &#x111;&#x1B0;&#x1EDD;ng d&#x1EAB;n. M&#x1ED9;t v&#xED; d&#x1EE5; v&#x1EC1; vi&#x1EC7;c n&#xE0;y l&#xE0; tri&#x1EC3;n khai m&#x1ED9;t t&#x1EC7;p phim tr&#xEA;n thi&#x1EBF;t b&#x1ECB; IOS, t&#x1EAD;p tin phim g&#x1ED1;c ph&#x1EA3;i c&#xF3; s&#x1EB5;n t&#x1EEB; m&#x1ED9;t v&#x1ECB; tr&#xED; trong h&#x1EC7; th&#x1ED1;ng t&#x1EAD;p tin s&#x1EBD; &#x111;&#x1B0;&#x1EE3;c ph&#xE1;t b&#x1EDF;i ch&#x1EE9;c n&#x103;ng PlayMovie.<br>
B&#x1EA5;t k&#x1EF3; m&#x1ED9;t t&#x1EC7;p n&#xE0;o &#x111;&#x1B0;&#x1EE3;c &#x111;&#x1EB7;t trong m&#x1ED9;t th&#x1B0; m&#x1EE5;c c&#xF3; t&#xEA;n l&#xE0; StreammingAssets (ph&#xE2;n bi&#x1EC7;t ch&#x1EEF; hoa v&#xE0; ch&#x1EEF; th&#x1B0;&#x1EDD;ng) trong m&#x1ED9;t project Unity s&#x1EBD; &#x111;&#x1B0;&#x1EE3;c sao ch&#xE9;p &#x111;&#xFA;ng nguy&#xEA;n v&#x103;n sang m&#x1ED9;t th&#x1B0; m&#x1EE5;c c&#x1EE5; th&#x1EC3; tr&#xEA;n m&#xE1;y &#x111;&#xED;ch. Ban jcos th&#x1EC3; truy xu&#x1EA5;t th&#x1B0; m&#x1EE5;c b&#x1EB1;ng th&#x1B0;&#x1EE3;c t&#xED;nh Application.streamingAssetPath. T&#x1ED1;t nh&#x1EA5;t s&#x1EED; d&#x1EE5;ng Application.streamingAssetPath &#x111;&#x1EC3; l&#x1EA5;y v&#x1ECB; tr&#xED; c&#x1EE7;a th&#x1B0; m&#x1EE5;c StreamingAssets, v&#xEC; n&#xF3; s&#x1EBD; lu&#xF4;n tr&#x1ECF; &#x111;&#x1EBF;n v&#x1ECB; tr&#xED; ch&#xED;nh x&#xE1;c tr&#xEA;n n&#x1EC1;n t&#x1EA3;ng n&#x1A1;i &#x1EE9;ng d&#x1EE5;ng ch&#x1EA1;y.<br>
V&#x1ECB; tr&#xED; c&#x1EE7;a th&#x1B0; m&#x1EE5;c n&#xE0;y thay &#x111;&#x1ED5;i theo n&#x1EC1;n t&#x1EA3;ng.</p>
<ul>
<li>Tr&#xEA;n m&#xE1;y t&#xED;nh &#x111;&#x1EC3; b&#xE0;n (Mac OS ho&#x1EB7;c Windows), v&#x1ECB; tr&#xED; c&#xE1;c t&#x1EC7;p c&#xF3; th&#x1EC3; l&#x1EA5;y b&#x1EB1;ng m&#xE3; sau:  <code>path = Application.dataPath + &quot;/StreamingAssets&quot;;</code></li>
<li>Tr&#xEA;n iOS, s&#x1EED; d&#x1EE5;ng : <code>path = Application.dataPath + &quot;/Raw&quot;;</code></li>
<li>Tr&#xEA;n Android, s&#x1EED; d&#x1EE5;ng: <code>path = &quot;jar:file://&quot; + Application.dataPath + &quot;!/assets/&quot;;</code></li>
</ul>
<p>Unity cho b&#x1EA1;n kh&#x1EA3; n&#x103;ng t&#xF9;y bi&#x1EBF;n. &#x110;&#xF3; l&#xE0; l&#xFD; do t&#x1EA1;i sao n&#xF3; th&#x1B0;&#x1EDD;ng xuy&#xEA;n l&#x1ED9;n x&#x1ED9;n, v&#xE0; v&#xEC; ch&#xFA;ng ta kh&#xF4;ng th&#x1EC3; n&#xF3;i v&#x1EC1; t&#x1ED5; ch&#x1EE9;c m&#xE0; kh&#xF4;ng c&#xF3; c&#x1EA5;u tr&#xFA;c th&#x1B0; m&#x1EE5;c d&#x1EF1; &#xE1;n ph&#xF9; h&#x1EE3;p. &#x110;&#xE2;y l&#xE0; m&#x1ED9;t v&#xED; d&#x1EE5; ch&#xFA;ng t&#xF4;i s&#x1EED; d&#x1EE5;ng trong th&#x1EF1; t&#x1EBF;</p>
<pre><code>|-- Assets
       |-- Animations
       |   |-- 2DAnimations
       |   |-- 3DAnimations
       |-- Editor           //Special Folder
       |-- Media
       |   |-- Audio
       |   |-- Video
       |-- Models
       |-- Materials
       |-- Plugins          //Special Folder
       |   |-- Android
       |   |-- iOS
       |   |-- Special
       |-- Prefabs
       |-- Resources        //Special Folder
       |   |-- Android
       |   |-- iOS
       |   |-- Common
       |-- Scenes
       |   |-- Levels
       |   |-- Others
       |-- Scripts
       |   |-- Editor
       |-- Shaders
       |-- StreamingAssets  //Special Folder
       |-- SandBox
       |-- Sprites
</code></pre>
<p>M&#x1ED9;t v&#xE0;i &#x111;i&#x1EC3;m quan tr&#x1ECD;ng c&#x1EA7;n ghi nh&#x1EDB;:</p>
<ul>
<li>Kh&#xF4;ng s&#x1EED; d&#x1EE5;ng d&#x1EA5;u c&#xE1;ch trong &#x111;&#x1EB7;t t&#xEA;n t&#x1EC7;p, v&#xEC; c&#xF4;ng c&#x1EE5; d&#xF2;ng l&#x1EC7;nh trong Unity3D kh&#xF4;ng x&#x1EED; l&#xFD; &#x111;&#x1B0;&#x1EDD;ng d&#x1EAB;n c&#xF3; d&#x1EA5;u c&#xE1;ch</li>
<li>Kh&#xF4;ng l&#x1B0;u tr&#x1EEF; b&#x1EA5;t k&#x1EF3; t&#x1EAD;p tin asset n&#xE0;o trong th&#x1B0; m&#x1EE5;c g&#x1ED1;c (Resources) . S&#x1EED; d&#x1EE5;ng th&#x1B0; m&#x1EE5;c con b&#x1EA5;t c&#x1EE9; khi n&#xE0;o</li>
<li>Kh&#xF4;ng t&#x1EA1;o b&#x1EA5;t k&#x1EF3; th&#x1B0; m&#x1EE5;c b&#x1ED5; sung n&#xE0;o trong th&#x1B0; m&#x1EE5;c g&#x1ED1;c (Resources), tr&#x1EEB; khi b&#x1EA1;n th&#x1EF1;c s&#x1EF1; c&#x1EA7;n.</li>
<li>H&#xE3;y &#x111;&#x1EB7;t t&#xEA;n m&#x1ED9;t c&#xE1;ch nh&#x1EA5;t qu&#xE1;n</li>
<li>S&#x1EED; d&#x1EE5;ng th&#x1B0; m&#x1EE5;c &quot;Third_Party&quot; &#x111;&#x1EC3; l&#x1B0;u tr&#x1EEF; c&#xE1;c asset  &#x111;&#x1B0;&#x1EE3;c nh&#x1EAD;p t&#x1EEB; Asset Store. Ch&#xFA;ng th&#x1B0;&#x1EDD;ng c&#xF3; c&#x1EA5;u tr&#xFA;c ri&#xEA;ng v&#xE0; kh&#xF4;ng n&#xEA;n thay &#x111;&#x1ED5;i</li>
<li>S&#x1EED; d&#x1EE5;ng &quot;SandBox&quot; cho b&#x1EA5;t k&#x1EF3; th&#x1EED; nghi&#x1EC7;m n&#xE0;o c&#x1EE7;a b&#x1EA1;n kh&#xF4;ng ho&#xE0;n to&#xE0;n ch&#x1EAF;c ch&#x1EB7;n. Khi b&#x1EA1;n &#x111;ang l&#xE0;m vi&#x1EC7;c tr&#xEA;n d&#x1EF1; &#xE1;n v&#x1EDB;i nh&#x1EEF;ng ng&#x1B0;&#x1EDD;i kh&#xE1;c, h&#xE3;y t&#x1EA1;o th&#x1B0; m&#x1EE5;c con SandBox c&#xE1; nh&#xE2;n c&#x1EE7;a b&#x1EA1;n nh&#x1B0; : SandBox/San</li>
</ul>
<h2 id="5cutrcphncpcasence">5. C&#x1EA5;u tr&#xFA;c ph&#xE2;n c&#x1EA5;p c&#x1EE7;a Sence</h2>
<p>B&#xEA;n c&#x1EA1;nh h&#x1EC7; th&#x1ED1;ng ph&#xE2;n c&#x1EA5;p c&#x1EE7;a project, c&#x169;ng c&#xF3; h&#x1EC7; th&#x1ED1;ng ph&#xE2;n c&#x1EA5;p c&#x1EE7;a Sence. Nh&#x1B0; tr&#xEA;n, ch&#xFA;ng t&#xF4;i s&#x1EBD; gi&#x1EDB;i thi&#x1EC7;u cho b&#x1EA1;n m&#x1ED9;t v&#xED; d&#x1EE5;. B&#x1EA1;n c&#xF3; th&#x1EC3; thay &#x111;&#x1ED5;i n&#xF3; theo nhu c&#x1EA7;u c&#x1EE7;a b&#x1EA1;n.</p>
<ul>
<li>Lights</li>
<li>Cameras</li>
<li>AR_Manager</li>
<li>World</li>
<li>GUI</li>
<li>Scene_Manager</li>
<li>_Dynamic</li>
</ul>
<p>M&#x1ED9;t v&#xE0;i &#x111;i&#x1EC3;m quan tr&#x1ECD;ng c&#x1EA7;n l&#x1B0;u &#xFD;:</p>
<ul>
<li>
<p>S&#x1EED; d&#x1EE5;ng c&#xE1;c gameobject tr&#x1ED1;ng (empty) nh&#x1B0; c&#xE1;c folder trong sence. S&#x1EAF;p x&#x1EBF;p m&#x1ED9;t c&#xE1;ch c&#x1EA9;n th&#x1EAD;n secne c&#x1EE7;a b&#x1EA1;n &#x111;&#x1EC3; c&#xF3; th&#x1EC3; d&#x1EC5; d&#xE0;ng t&#xEC;m c&#xE1;c &#x111;&#x1ED1;i t&#x1B0;&#x1EE3;ng. T&#x1EA5;t c&#x1EA3; c&#xE1;c gameobject tr&#x1ED1;ng c&#x1EA7;n ph&#x1EA3;i &#x111;&#x1EB7;t position (0,0,0) v&#xE0; rotision v&#xE0; scale m&#x1EB7;c &#x111;&#x1ECB;nh</p>
</li>
<li>
<p>Khi b&#x1EA1;n kh&#x1EDF;i t&#x1EA1;o m&#x1ED9;t &#x111;&#x1ED1;i t&#x1B0;&#x1EE3;ng trong th&#x1EDD;i gian ch&#x1EA1;y, h&#xE3;y nh&#x1EDB; &#x111;&#x1EB7;t &#x111;&#x1ED1;i t&#x1B0;&#x1EE3;ng &#x111;&#xF3; trong _Dynamic</p>
</li>
<li>
<p>&#x110;&#x1EB7;t c&#xE1;c prefabs v&#xE0; folders (empty gameobject) &#x1EDF; (0,0,0). N&#x1EBF;u tranform c&#x1EE7;a n&#xF3; kh&#xF4;ng &#x111;&#x1B0;&#x1EE3;c s&#x1EED; d&#x1EE5;ng &#x111;&#x1EC3; &#x111;&#x1ECB;nh v&#x1ECB; &#x111;&#x1ED1;i t&#x1B0;&#x1EE3;ng, n&#xF3; ph&#x1EA3;i &#x1EDF; g&#x1ED1;c. B&#x1EB1;ng c&#xE1;ch &#x111;&#xF3;, c&#xF3; &#xED;t nguy c&#x1A1; g&#x1EB7;p ph&#x1EA3;i s&#x1EF1; c&#x1ED1; v&#x1EDB;i kh&#xF4;ng gian &#x111;&#x1ECB;a ph&#x1B0;&#x1A1;ng v&#xE0; th&#x1EBF; gi&#x1EDB;i</p>
</li>
<li>
<p>&#x110;&#x1EB7;t nh&#xE2;n v&#x1EAD;t v&#xE0; &#x111;&#x1ED1;i t&#x1B0;&#x1EE3;ng t&#x1EA1;i pivots, kh&#xF4;ng t&#x1EA1;i centre. &#x110;i&#x1EC1;u n&#xE0;y l&#xE0;m cho n&#xF3; d&#x1EC5; d&#xE0;ng &#x111;&#x1EB7;t c&#xE1;c nh&#xE2;n v&#x1EAD;t v&#xE0; c&#xE1;c &#x111;&#xF3;i t&#x1B0;&#x1EE3;ng tr&#xEA;n m&#x1ED9;t s&#xE0;n m&#x1ED9;t c&#xE1;ch ch&#xED;nh x&#xE1;c. N&#xF3; c&#x169;ng d&#x1EC5; d&#xE0;ng h&#x1A1;n &#x111;&#x1EC3; l&#xE0;m vi&#x1EC7;c v&#x1EDB;i 3D nh&#x1B0; th&#x1EC3; l&#xE0; 2D cho logic tr&#xF2; ch&#x1A1;i, AI v&#xE0; th&#x1EAD;m ch&#x1EC9; c&#x1EA3; v&#x1EAD;t l&#xFD;.</p>
</li>
<li>
<p>L&#xE0;m cho t&#x1EA5;t c&#x1EA3; c&#xE1;c mesh ph&#x1EA3;i theo m&#x1ED9;t h&#x1B0;&#x1EDB;ng (tr&#x1EE5;c z d&#x1B0;&#x1A1;ng ho&#x1EB7;c &#xE2;m). &#x110;i&#x1EC1;u n&#xE0;y &#xE1;p dung cho c&#xE1;c mesh nh&#x1B0; k&#xFD; t&#x1EF1; v&#xE0; c&#xE1;c &#x111;&#x1ED1;i t&#x1B0;&#x1EE3;ng kh&#xE1;c c&#xF3; kh&#xE1;i ni&#x1EC7;m h&#x1B0;&#x1EDB;ng &#x111;&#x1ED1;i di&#x1EC7;n. Nhi&#x1EC1;u thu&#x1EAD;t to&#xE1;n &#x111;&#x1B0;&#x1EE3;c &#x111;&#x1A1;n gi&#x1EA3;n h&#xF3;a n&#x1EBF;u m&#xF3;i th&#x1EE9; &#x111;&#x1EC1;u c&#xF3; c&#xF9;ng h&#x1B0;&#x1EDB;ng &#x111;&#x1ED1;i di&#x1EC7;n.</p>
</li>
<li>
<p>L&#x1EA5;y scale &#x111;&#xFA;ng ngay t&#x1EEB; &#x111;&#x1EA7;u. T&#x1EA1;o t&#x1EF7; l&#x1EC7; sao cho t&#x1EA5;t c&#x1EA3; ch&#xFA;ng c&#xF3; th&#x1EC3; &#x111;&#x1B0;&#x1EE3;c nh&#x1EAD;p v&#x1EDB;i h&#x1EC7; s&#x1ED1; t&#x1EF7; l&#x1EC7; l&#xE0; 1 v&#xE0; transforms c&#x1EE7;a ch&#xFA;ng c&#xF3; th&#x1EC3; &#x111;&#x1B0;&#x1EE3;c chia theo (1,1,1). S&#x1EED; d&#x1EE5;ng &#x111;&#x1ED1;i t&#x1B0;&#x1EE3;ng tham chi&#x1EBF;u (Unity cube) &#x111;&#x1EC3; so s&#xE1;nh quy m&#xF4; d&#x1EC5; d&#xE0;ng. Ch&#x1ECD;n m&#x1ED9;t &#x111;&#x1A1;n v&#x1ECB; Unity  th&#x1ED1;ng nh&#x1EA5;t, ph&#xF9; h&#x1EE3;p v&#x1EDB;i tr&#xF2; ch&#x1A1;i/project c&#x1EE7;a b&#x1EA1;n</p>
</li>
</ul>
<h2 id="6sdnghqunlphinbnbntrongunity">6. S&#x1EED; d&#x1EE5;ng h&#x1EC7; qu&#x1EA3;n l&#xFD; phi&#xEA;n b&#x1EA3;n b&#xEA;n trong Unity</h2>
<p>B&#x1EA1;n c&#xF3; th&#x1EC3; s&#x1EED; d&#x1EE5;ng b&#x1EA5;t k&#x1EF3; h&#x1EC7; qu&#x1EA3;n l&#xFD; n&#xE0;o: Git, Subversion ho&#x1EB7;c b&#x1EA5;t k&#x1EF3; VCS n&#xE0;o kh&#xE1;c. B&#x1EA1;n n&#xEA;n t&#x1EAD;p trung t&#xEC;m hi&#x1EC3;u k&#x1EF9; v&#x1EC1; t&#xED;nh n&#x103;ng c&#x1EE7;a VCS m&#xE0; b&#x1EA1;n ch&#x1ECD;n &#x111;&#x1EC3; ph&#x1EE5;c v&#x1EE5; cho vi&#x1EC7;c qu&#x1EA3;n l&#xFD; phi&#xEA;n b&#x1EA3;n m&#x1ED9;t c&#xE1;ch t&#x1ED1;t nh&#x1EA5;t. Nhi&#x1EC1;u ng&#x1B0;&#x1EDD;i &#x111;ang s&#x1EED; d&#x1EE5;ng nh&#x1EEF;ng h&#x1EC7; th&#x1ED1;ng VCS n&#xE0;y v&#x1EDB;i m&#x1EE5;c &#x111;&#xED;ch nh&#x1B0; m&#x1ED9;t gi&#x1EA3;i ph&#xE1;p sao l&#x1B0;u v&#xE0; &#x111;&#x1ED3;ng b&#x1ED9; h&#xF3;a.</p>
<h3 id="thitlphthngqunlphinbnviunity">Thi&#x1EBF;t l&#x1EAD;p h&#x1EC7; th&#x1ED1;ng qu&#x1EA3;n l&#xFD; phi&#xEA;n b&#x1EA3;n v&#x1EDB;i Unity</h3>
<p>B&#x1EA1;n s&#x1EBD; th&#x1EA5;y r&#x1EB1;ng trong h&#x1EA7;u h&#x1EBF;t project Unity c&#xF3; kh&#xE1; nhi&#x1EC1;u t&#x1EAD;p tin v&#xE0; th&#x1B0; m&#x1EE5;c. Tuy nhi&#xEA;n, ch&#x1EC9; c&#xF3; 3 th&#x1B0; m&#x1EE5;c c&#x1EA7;n &#x111;&#x1B0;&#x1EE3;c ki&#x1EC3;m so&#xE1;t l&#xE0;: Assets, Packages v&#xE0; ProjectSettings. Nh&#x1EEF;ng th&#xE0;nh ph&#x1EA7;n c&#xF2;n l&#x1EA1;i &#x111;&#x1B0;&#x1EE3;c t&#x1EA1;o ra t&#x1EEB; ch&#xFA;ng.<br>
D&#x1B0;&#x1EDB;i &#x111;&#xE2;y l&#xE0; t&#xF3;m t&#x1EAF;t v&#x1EC1; t&#x1EA5;t c&#x1EA3; c&#xE1;c t&#x1EC7;p v&#xE0; th&#x1B0; m&#x1EE5;c</p>
<ul>
<li><strong>Assets</strong>: Th&#x1B0; m&#x1EE5;c ch&#x1B0;a t&#x1EA5;t c&#x1EA3; t&#xE0;i nguy&#xEA;n c&#x1EE7;a game bao g&#x1ED3;m: scripts, textures, sound, tr&#xEC;nh editors ... &#x110;&#xE2;y l&#xE0; th&#x1B0; m&#x1EE5;c quan tr&#x1ECD;ng nh&#x1EA5;t c&#x1EE7;a project.</li>
<li>Library: b&#x1ED9; nh&#x1EDB; cache c&#x1EE5;c b&#x1ED9; cho c&#xE1;c n&#x1ED9;i dung &#x111;&#xE3; nh&#x1EAD;p, khi s&#x1EED; d&#x1EE5;ng VCS c&#x1EA7;n lo&#x1EA1;i b&#x1ECF; ho&#xE0;n to&#xE0;n</li>
<li><strong>Packages</strong>: Th&#x1B0; m&#x1EE5;c n&#xE0;y ch&#x1B0;a c&#xE1;c t&#x1EC7;p d&#x1B0;&#x1EDB;i &#x111;&#x1ECB;nh d&#x1EA1;ng JSON &#x111;&#x1B0;&#x1EE3;c s&#x1EED; d&#x1EE5;ng &#x111;&#x1EC3; duy tr&#xEC; li&#xEA;n k&#x1EBF;t ph&#x1EE5; thu&#x1ED9;c</li>
<li><strong>ProjectSettings</strong>: trong th&#x1B0; m&#x1EE5;c n&#xE0;y ch&#x1EE9;a t&#x1EA5;t c&#xE1;c c&#xE1;c thi&#x1EBF;t l&#x1EAD;p c&#x1EE7;a project nh&#x1B0;: Physic, Tags, Player Settings ...N&#xF3;i c&#xE1;ch kh&#xE1;c, m&#x1ECD;i th&#x1EE9; b&#x1EA1;n thi&#x1EBF;t l&#x1EAD;p t&#x1EEB; Edit -&gt; Project Settings s&#x1EBD; &#x111;&#x1B0;&#x1EE3;c chuy&#xEA;n v&#xE0;o th&#x1B0; m&#x1EE5;c n&#xE0;y</li>
<li>Temp: c&#xE1;ch th&#x1B0; m&#x1EE5;c cho c&#xE1;c t&#x1EC7;p t&#x1EA1;m &#x111;&#x1B0;&#x1EE3;c t&#x1EA1;o trong qu&#xE1; tr&#xEC;nh build, t&#xEA;p jddaau ti&#xEA;n &#x111;&#x1B0;&#x1EE3;c s&#x1EED; d&#x1EE5;ng b&#x1EDF;i MonoDevelop, t&#x1EBF;p th&#x1EE9; 2 b&#x1EDF;i Unity</li>
<li>ProjectName.sln : c&#xE1;c t&#x1EC7;p gi&#x1EA3;i ph&#xE1;p cho c&#xE1;c IDE nh&#x1B0; Visual Studio</li>
</ul>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/09/Unitycodestructure.png" alt="Unity cho ng&#x1B0;&#x1EDD;i b&#x1EAF;t &#x111;&#x1EA7;u : C&#x1EA5;u tr&#xFA;c th&#x1B0; m&#x1EE5;c v&#xE0; source code" loading="lazy"></p>
<p>Tr&#x1B0;&#x1EDB;c khi th&#x1EF1;c hi&#x1EC7;n vi&#x1EC7;c qu&#x1EA3;n l&#xFD; phi&#xEA;n b&#x1EA3;n, b&#x1EA1;n c&#x1EA7;n ph&#x1EA3;i c&#x1EA5;u h&#xEC;nh Project &#x111;&#x1EC3; n&#xF3; t&#x1B0;&#x1A1;ng th&#xED;ch v&#x1EDB;i vi&#x1EC7;c l&#x1B0;u tr&#x1EEF; trong VCS. Th&#x1EF1;c hi&#x1EC7;n c&#xE1;c b&#x1B0;&#x1EDB;c nh&#x1B0; sau:</p>
<ul>
<li>Chuy&#x1EC3;n sang ch&#x1EBF; &#x111;&#x1ED9; Visible Meta Files in Edit &#x2192; Project Settings &#x2192; Editor &#x2192; Version Control Mode &#x2192; Visible Meta Files.</li>
<li>Chuy&#x1EC3;n sang Force Text in Edit &#x2192; Project Settings &#x2192; Editor &#x2192; Asset Serialization Mode</li>
</ul>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/09/UnitySettings.png" alt="Unity cho ng&#x1B0;&#x1EDD;i b&#x1EAF;t &#x111;&#x1EA7;u : C&#x1EA5;u tr&#xFA;c th&#x1B0; m&#x1EE5;c v&#xE0; source code" loading="lazy"></p>
<p>V&#x1EDB;i thi&#x1EBF;t l&#x1EAD;p n&#xE0;y s&#x1EBD; hi&#x1EC3;n th&#x1ECB; m&#x1ED9;t t&#x1EC7;p v&#x103;n b&#x1EA3;n cho m&#x1ECD;i n&#x1ED9;i dung trong th&#x1B0; m&#x1EE5;c Assets<br>
C&#xE1;c t&#x1EC7;p c&#xF3; ph&#x1EA7;n m&#x1EDF; r&#x1ED9;ng l&#xE0; <code>.meta</code> v&#x1EDB;i ph&#x1EA7;n &#x111;&#x1EA7;u ti&#xEA;n l&#xE0; t&#xEA;n &#x111;&#x1EA9;y &#x111;&#x1EE7; c&#x1EE7;a n&#x1ED9;i dung li&#xEA;n k&#x1EBF;t v&#x1EDB;i n&#xF3;. Vi&#x1EC7;c di chuy&#x1EC3;n v&#xE0; &#x111;&#x1ED5;i t&#xEA;n n&#x1ED9;i dung trong Unity c&#x169;ng s&#x1EBD; &#x111;&#x1B0;&#x1EE3;c c&#x1EAD;p nh&#x1EAD;t v&#xE0;o c&#xE1;c t&#x1EC7;p <code>.meta</code> li&#xEA;n quan. Tuy nhi&#xEA;n, n&#x1EBF;u b&#x1EA1;n di chuy&#x1EC3;n ho&#x1EB7;c &#x111;&#x1ED5;i t&#xEA;n n&#x1ED9;i dung t&#x1EEB; m&#x1ED9;t c&#xF4;ng c&#x1EE5; b&#xEA;n ngo&#xE0;i, h&#xE3;y &#x111;&#xE3;m b&#x1EA3;o r&#x1EB1;ng &#x111;&#xE3; &#x111;&#x1ED3;ng b&#x1ED9; h&#xF3;a c&#xE1;c t&#x1EC7;p .meta li&#xEA;n quan.</p>
<p>V&#xED; d&#x1EE5; : t&#x1EA1;o m&#x1ED9;t d&#x1EF1; &#xE1;n m&#x1EDB;i v&#xE0; nh&#x1EAD;p n&#xF3; v&#xE0;o kho l&#x1B0;u tr&#x1EEF; VCS (GIT)</p>
<ol>
<li>T&#x1EA1;o m&#x1ED9;t project m&#x1EDB;i trong Unity v&#xE0; &#x111;&#x1EB7;t t&#xEA;n n&#xF3; l&#xE0; ReverieSample.</li>
<li>K&#xED;ch ho&#x1EA1;t Visible Meta files in Edit-&gt;Project Settings-&gt;Editor</li>
<li>Chuy&#x1EC3;n Force Text in Edit &#x2192; Project Settings &#x2192; Editor &#x2192; Asset Serialization Mode</li>
<li>T&#x1EAF;t Unity (&#x111;&#x1EA3;m b&#x1EA3;o r&#x1EB1;ng t&#x1EA5;t c&#x1EA3; c&#xE1;c t&#x1EAD;p tin &#x111;&#xE3; &#x111;&#x1B0;&#x1EE3;c l&#x1B0;u)</li>
<li>Thi&#x1EBF;t l&#x1EAD;p b&#x1ED9; l&#x1ECD;c <code>.gitignore</code> cho c&#xE1;c th&#x1B0; m&#x1EE5;c v&#xE0; t&#x1EC7;p kh&#xF4;ng c&#x1EA7;n thi&#x1EBF;t</li>
<li>Nh&#x1EAD;p project v&#xE0;o VCS b&#x1EB1;ng c&#xE1;ch s&#x1EED; d&#x1EE5;ng c&#xF4;ng c&#x1EE5; GUI ho&#x1EB7;c d&#xF2;ng l&#x1EC7;nh v&#xE0; &#x111;&#x1EA9;y ch&#xFA;ng l&#xEA;n VCS remote/ local Responsitory</li>
<li>Ki&#x1EC3;m tra c&#xE1;c th&#x1B0; m&#x1EE5;c Assets, Packages v&#xE0; ProjectSettings &#x111;&#xE3; c&#xF3; trong VCS ch&#x1B0;a</li>
<li>M&#x1EDF; project v&#x1EDB;i Unity. Vi&#x1EC7;c m&#x1EDF; project s&#x1EBD; t&#x1EA1;o l&#x1EA1;i th&#x1B0; m&#x1EE5;c Library v&#xE0; c&#xE1;c t&#x1EC7;p th&#x1B0; m&#x1EE5;c c&#x1EA7;n thi&#x1EBF;t kh&#xE1;c</li>
<li>Cu&#x1ED1;i c&#xF9;ng, b&#x1EA1;n c&#xF3; th&#x1EC3; th&#x1EF1;c hi&#x1EC7;n v&#xE0; c&#x1EAD;p nh&#x1EAD;t c&#xE1;c thay &#x111;&#x1ED5;i. Project &#x111;&#xE3; s&#x1EB5;n s&#xE0;ng s&#x1EED; d&#x1EE5;ng.</li>
</ol>
<p>File <code>.gitignore</code> : <a href="http://www.arreverie.com/blogs/wp-content/uploads/resources/.gitignore?ref=blog.arrow-tech.vn">http://www.arreverie.com/blogs/wp-content/uploads/resources/.gitignore</a></p>
<h2 id="7prefabs">7. Prefabs</h2>
<p>S&#x1EED; d&#x1EE5;ng prefabs cho m&#x1ECD;i th&#x1EE9;. Prefabs trong Unity l&#xE0; gi&#x1EA3;i ph&#xE1;p t&#x1ED1;t nh&#x1EA5;t m&#xE0; b&#x1EA1;n t&#xEC;m th&#x1EA5;y &#x111;&#x1EC3; chia s&#x1EBB; c&#xE1;c c&#x1EA5;u tr&#xFA;c ph&#xE2;n c&#x1EA5;p &#x111;&#x1B0;&#x1EE3;c c&#x1EA5;u h&#xEC;nh s&#x1EB5;n. N&#xF3;i chung, h&#xE3;y th&#x1EED; &#x111;&#x1EC3; prefab t&#x1EA5;t c&#x1EA3; m&#x1ECD;i th&#x1EE9; m&#xE0; b&#x1EA1;n &#x111;&#x1B0;a v&#xE0; Sence. &#x110;i&#x1EC1;u n&#xE0;y gi&#xFA;p d&#x1EC5; d&#xE0;ng th&#x1EF1;c hi&#x1EC7;n c&#xE1;c thay &#x111;&#x1ED5;i m&#xE0; kh&#xF4;ng c&#x1EA7;n thay &#x111;&#x1ED5;i Sence.<br>
L&#xFD; do t&#x1EA1;i sao b&#x1EA1;n n&#xEA;n s&#x1EED; d&#x1EE5;ng Prefabs l&#xE0; khi c&#xF3; m&#x1ED9;t thay &#x111;&#x1ED5;i v&#x1EDB;i prefab, th&#xEC; n&#xF3; s&#x1EBD; thay &#x111;&#x1ED5;i to&#xE0;n b&#x1ED9; &#x1EDF; c&#xE1;c Sence m&#xE0; prefab &#x111;&#x1B0;&#x1EE3;c s&#x1EED; d&#x1EE5;ng. B&#x1EA1;n c&#xF3; 100 level v&#xE0; mu&#x1ED1;n th&#xEA;m hi&#x1EC7;u &#x1EE9;ng camera v&#xE0;o t&#x1EA5;t c&#x1EA3; ch&#xFA;ng? Kh&#xF4;ng th&#xE0;nh v&#x1EA5;n &#x111;&#x1EC1;! N&#x1EBF;u camera c&#x1EE7;a b&#x1EA1;n l&#xE0; prefab, ch&#x1EC9; c&#x1EA7;n th&#xEA;m hi&#x1EC7;u &#x1EE9;ng &#x111;&#xF3; v&#xE0;o prefab c&#x1EE7;a m&#xE1;y &#x1EA3;nh.<br>
S&#x1EED; d&#x1EE5;ng prefabs ri&#xEA;ng bi&#x1EC7;t cho c&#xE1;c tr&#x1B0;&#x1EDD;ng h&#x1EE3;p ri&#xEA;ng bi&#x1EC7;t. N&#x1EBF;u b&#x1EA1;n c&#xF3; hai lo&#x1EA1;i enemy v&#xE0; ch&#xFA;ng ch&#x1EC9; kh&#xE1;ch nhau b&#x1EDF;i thu&#x1ED9;c t&#xED;nh c&#x1EE7;a ch&#xFA;ng, h&#xE3;y t&#x1EA1;o c&#xE1;c prefab ri&#xEA;ng bi&#x1EC7;t cho c&#xE1;ch thu&#x1ED9;c t&#xED;nh v&#xE0; li&#xEA;n k&#x1EBF;t ch&#xFA;ng. &#x110;i&#x1EC1;u n&#xE0;y gi&#xFA;p cho</p>
<ul>
<li>M&#x1ED7;i lo&#x1EA1;i &#x111;&#x1B0;&#x1EE3;c thay &#x111;&#x1ED5;i &#x1EDF; m&#x1ED9;t n&#x1A1;i</li>
<li>Th&#x1EF1;c hi&#x1EC7;n thay &#x111;&#x1ED5;i m&#xE0; kh&#xF4;ng c&#x1EA7;n thay &#x111;&#x1ED5;i Sence</li>
</ul>
<p>Li&#xEA;n k&#x1EBF;t prefabs t&#x1EDB;i prefabs; kh&#xF4;ng li&#xEA;n k&#x1EBF;t c&#xE1;c c&#xE1; th&#x1EC3; t&#x1EDB;i c&#xE1;c c&#xE1; th&#x1EC3;. C&#xE1;c li&#xEA;n k&#x1EBF;t &#x111;&#x1EBF;n prefabs &#x111;&#x1B0;&#x1EE3;c duy tr&#xEC; khi &#x111;&#x1EB7;t m&#x1ED9;t prefabs v&#xE0;o 1 sence; li&#xEA;n k&#x1EBF;t &#x111;&#x1EBF;n c&#xE1;c c&#xE1; th&#x1EC3; th&#xEC; kh&#xF4;ng. Li&#xEA;n k&#x1EBF;t v&#x1EDB;i prefabs c&#xF3; th&#x1EC3; gi&#x1EA3;m vi&#x1EC7;c c&#xE0;i &#x111;&#x1EB7;t sence v&#xE0; vi&#x1EC7;c thay &#x111;&#x1ED5;i trong sences</p>
<p>C&#xE0;ng nhi&#x1EC1;u c&#xE0;ng t&#x1ED1;t, thi&#x1EBF;t l&#x1EAD;p li&#xEA;n k&#x1EBF;t gi&#x1EEF;a c&#xE1;c c&#xE1; th&#x1EC3; m&#x1ED9;t c&#xE1;ch t&#x1EF1; &#x111;&#x1ED9;ng. N&#x1EBF;u b&#x1EA1;n c&#x1EA7;n li&#xEA;n k&#x1EBF;t c&#xE1;c c&#xE1; th&#x1EC3; th&#xE3;y thi&#x1EBF;t l&#x1EAD;p li&#xEA;n k&#x1EBF;t theo ch&#x1B0;&#x1A1;ng tr&#xEC;nh. V&#xED; d&#x1EE5;, prefab player c&#xF3; th&#x1EC3; t&#x1EF1; &#x111;&#x103;ng k&#xFD; v&#x1EDB;i GameManager khi n&#xF3; kh&#x1EDF;i &#x111;&#x1ED9;ng, ho&#x1EB7;c GameManager c&#xF3; th&#x1EC3; t&#xEC;m th&#x1EA5;y c&#xE1; th&#x1EC3; Player Prefabs khi n&#xF3; b&#x1EAF;t &#x111;&#x1EA7;u.</p>
<p>Kh&#xF4;ng &#x111;&#x1EB7;t mest v&#xE0;o prefabs n&#x1EBF;u b&#x1EA1;n mu&#x1ED1;n th&#xEA;m c&#xE1;c scripts kh&#xE1;c. Khi b&#x1EA1;n t&#x1EA1;o prefab t&#x1EEB; m&#x1ED9;t mest, t&#x1EA1;o m&#x1ED9;t gameobject r&#x1ED7;ng l&#xE0;m object cha, v&#xE0; &#x111;&#x1EB7;t n&#xF3; &#x1EDF; root. &#x110;&#x1EB7;t script v&#xE0;o root, kh&#xF4;ng &#x111;&#x1EB7;t tr&#xEA;n mesh. B&#x1EB1;ng c&#xE1;ch &#x111;&#xF3;, vi&#x1EC7;c thay mesh b&#x1EB1;ng m&#x1ED9;t mesh kh&#xE1;c s&#x1EBD; d&#x1EC5; d&#xE0;ng h&#x1A1;n v&#xE0; kh&#xF4;ng l&#xE0;m m&#x1EA5;t d&#x1EEF; li&#x1EC7;u m&#xE0; b&#x1EA1;n &#x111;&#xE3; thi&#x1EBF;t l&#x1EAD;p trong ch&#x1EE7; th&#x1EC3;.</p>
<h2 id="8documentation">8. Documentation</h2>
<p>H&#x1EA7;u h&#x1EBF;t c&#xE1;c t&#xE0;i li&#x1EC7;u &#x111;&#x1B0;&#x1EE3;c ch&#xFA; th&#xED;ch trong m&#xE3; code tuy nhi&#xEA;n m&#x1ED9;t s&#x1ED1; c&#x1EA7;n ghi l&#x1EA1;i &#x1EDF; b&#xEA;n ngo&#xE0;i. Ch&#xFA;ng ta c&#x1EA7;n duy tr&#xEC; t&#x1EC7;p <code>README.txt</code> trong project c&#x1EE7;a m&#xEC;nh</p>
<p>T&#xE0;i li&#x1EC7;u &#x111;&#xE1;p &#x1EE9;ng nh&#x1EEF;ng &#x111;i&#x1EC1;u sau:</p>
<ul>
<li>S&#x1A1; &#x111;&#x1ED3; kh&#x1ED1;i chi ti&#x1EBF;t v&#xE0; s&#x1A1; &#x111;&#x1ED3; lu&#x1ED3;ng c&#x1EE7;a project gi&#xFA;p hi&#x1EC3;u r&#xF5; ki&#x1EBF;n tr&#xFA;c project</li>
<li>C&#xE1;c chi ti&#x1EBF;t c&#x1EE7;a script v&#xE0; m&#x1ED9;t s&#x1ED1; th&#xF4;ng tin v&#x1EC1; c&#xE1;c ti&#xEA;u chu&#x1EA9;n code &#x111;&#x1B0;&#x1EE3;c tu&#xE2;n th&#x1EE7; trong project</li>
<li>L&#x1EDB;p &#x111;&#x1B0;&#x1EE3;c d&#xF9;ng (cho collision, culling v&#xE0; raycasting)</li>
<li>C&#xE1;c Tag &#x111;&#x1B0;&#x1EE3;c s&#x1EED; d&#x1EE5;ng</li>
<li>GUI cho c&#xE1;c l&#x1EDB;p (nh&#x1EEF;ng g&#xEC; s&#x1EBD; hi&#x1EC3;n th&#x1ECB;)</li>
<li>Chi ti&#x1EBF;t thi&#x1EBF;t l&#x1EAD;p Sence</li>
<li>C&#x1EA5;u tr&#xFA;c Prefabs</li>
<li>C&#xE1;c l&#x1EDB;p Animation v&#xE0; c&#xE1; th&#xF4;ng tin li&#xEA;n quan &#x111;&#x1EBF;n Animation</li>
</ul>
<h2 id="9ktlun">9. K&#x1EBF;t lu&#x1EAD;n</h2>
<p>Ch&#xFA;ng t&#xF4;i v&#x1EEB;a &#x111;&#x1B0;a ra m&#x1ED9;t c&#xE1;ch t&#x1ED5;ng quan ng&#x1EAF;n g&#x1ECD;n v&#x1EC1; vi&#x1EC7;c x&#x1EED; l&#xFD; c&#x1EA5;u tr&#xFA;c. Nh&#x1EEF;ng g&#xEC; ph&#xF9; h&#x1EE3;p v&#x1EDB;i ch&#xFA;ng t&#xF4;i c&#xF3; th&#x1EC3; kh&#xF4;ng hi&#x1EC7;u qu&#x1EA3; &#x111;&#x1ED1;i v&#x1EDB;i b&#x1EA1;n, do &#x111;&#xF3; &#x111;&#x1EEB;ng ng&#x1EA7;n ng&#x1EA1;i &#x111;i&#x1EC1;u ch&#x1EC9;nh m&#x1ECD;i th&#x1EE9; cho ph&#xF9; h&#x1EE3;p v&#x1EDB;i s&#x1EDF; th&#xED;ch c&#x1EE7;a ri&#xEA;ng b&#x1EA1;n. C&#xE1;ch ti&#x1EBF;p c&#x1EAD;n m&#xE0; ch&#xFA;ng t&#xF4;i &#x111;&#xE3; s&#x1EED; d&#x1EE5;ng &#x1EDF; &#x111;&#xE2;y l&#xE0; th&#x1EED; nghi&#x1EC7;m m&#x1ED9;t c&#xE1;i g&#xEC; &#x111;&#xF3;, ch&#x1EC9;nh s&#x1EED;a nh&#x1EEF;ng g&#xEC; kh&#xF4;ng hi&#x1EC7;u qu&#x1EA3;, sau &#x111;&#xF3; th&#x1EED; l&#x1EA1;i. &#x110;&#xF3; l&#xE0; b&#xED; quy&#x1EBF;t c&#x1EE7;a th&#xE0;nh c&#xF4;ng.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[[Unity] Hướng dẫn làm biến dạng và tô màu mesh (Deform & paint color on mesh) runtime trên mobile (p2)]]></title><description><![CDATA[Trong phần 2, mình sẽ hướng dẫn 2 bước còn lại là tô màu xung quanh vị trí làm lõm và update lại collider cho mesh.]]></description><link>https://blog.arrow-tech.vn/unity-huong-dan-lam-bien-dang-va-to-mau-mesh-deform-paint-color-on-mesh-runtime-tren-mobile-p2/</link><guid isPermaLink="false">63915acd7a2f410001205db5</guid><category><![CDATA[Unity]]></category><dc:creator><![CDATA[Datbq ]]></dc:creator><pubDate>Wed, 05 Sep 2018 08:48:12 GMT</pubDate><media:content url="https://blog.arrow-tech.vn/content/images/2018/09/687474703a2f2f696d672e796f75747562652e636f6d2f76692f5457474b355551364b73552f302e6a7067.jpeg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://blog.arrow-tech.vn/content/images/2018/09/687474703a2f2f696d672e796f75747562652e636f6d2f76692f5457474b355551364b73552f302e6a7067.jpeg" alt="[Unity] H&#x1B0;&#x1EDB;ng d&#x1EAB;n l&#xE0;m bi&#x1EBF;n d&#x1EA1;ng v&#xE0; t&#xF4; m&#xE0;u mesh (Deform &amp; paint color on mesh) runtime tr&#xEA;n mobile (p2)"><p><a href="https://blog.arrow-tech.vn/unity-mesh-deformation-bien-dang-mesh-runtime-tren-mobile/">[Unity] H&#x1B0;&#x1EDB;ng d&#x1EAB;n l&#xE0;m bi&#x1EBF;n d&#x1EA1;ng v&#xE0; t&#xF4; m&#xE0;u mesh (Deform &amp; paint color on mesh) runtime tr&#xEA;n mobile (p1)</a></p>
<blockquote>
<p>Trong ph&#x1EA7;n 2, m&#xEC;nh s&#x1EBD; h&#x1B0;&#x1EDB;ng d&#x1EAB;n 2 b&#x1B0;&#x1EDB;c c&#xF2;n l&#x1EA1;i l&#xE0; t&#xF4; m&#xE0;u xung quanh v&#x1ECB; tr&#xED; l&#xE0;m l&#xF5;m v&#xE0; update l&#x1EA1;i collider cho mesh.</p>
</blockquote>
<p><strong>T&#xF4; m&#xE0;u xung quanh v&#x1ECB; tr&#xED; l&#xE0;m l&#xF5;m</strong></p>
<p>C&#xF3; nhi&#x1EC1;u c&#xE1;ch &#x111;&#x1EC3; t&#xF4; m&#xE0;u l&#xEA;n texture trong real time. Tuy nhi&#xEA;n, &#x111;&#x1EC3; s&#x1EED; d&#x1EE5;ng &#x111;&#x1B0;&#x1EE3;c tr&#xEA;n low-end device th&#xEC; kh&#xF4;ng c&#xF3; nhi&#x1EC1;u c&#xE1;ch c&#xF3; th&#x1EC3; th&#x1EF1;c hi&#x1EC7;n. Trong b&#xE0;i vi&#x1EBF;t n&#xE0;y, m&#xEC;nh s&#x1EBD; h&#x1B0;&#x1EDB;ng d&#x1EAB;n c&#xE1;ch s&#x1EED; d&#x1EE5;ng RenderTexture.<br>
RenderTexture l&#xE0; m&#x1ED9;t lo&#x1EA1;i Texture &#x111;&#x1EB7;c bi&#x1EC7;t cho ph&#xE9;p t&#x1EA1;o v&#xE0; update runtime. &#x110;&#x1EC3; s&#x1EED; d&#x1EE5;ng n&#xF3;, b&#x1EA1;n c&#x1EA7;n t&#x1EA1;o v&#xE0; ch&#x1EC9; &#x111;&#x1ECB;nh m&#x1ED9;t camera render v&#xE0;o n&#xF3;. RenderTexture hi&#x1EC3;n th&#x1ECB; nh&#x1EEF;ng g&#xEC; camera (m&#xE0; n&#xF3; g&#x1EAF;n v&#xE0;o) render ra trong real time.<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/09/Inspector-RenderTexture.png" alt="[Unity] H&#x1B0;&#x1EDB;ng d&#x1EAB;n l&#xE0;m bi&#x1EBF;n d&#x1EA1;ng v&#xE0; t&#xF4; m&#xE0;u mesh (Deform &amp; paint color on mesh) runtime tr&#xEA;n mobile (p2)" loading="lazy"><br>
&#x110;&#x1EC3; l&#xE0;m &#x111;&#x1B0;&#x1EE3;c &#x111;i&#x1EC1;u n&#xE0;y, ch&#xFA;ng ta c&#x1EA7;n th&#x1EF1;c hi&#x1EC7;n 2 vi&#x1EC7;c:</p>
<ul>
<li>T&#xEC;m to&#x1EA1; &#x111;&#x1ED9; uv map c&#x1EE7;a texture terrain d&#x1EF1;a tr&#xEA;n &#x111;i&#x1EC3;m va ch&#x1EA1;m.</li>
<li>T&#xF4; m&#xE0;u l&#xEA;n texture l&#xFA;c runtime d&#x1EF1;a tr&#xEA;n RenderTexture.</li>
</ul>
<p><strong>1. T&#xEC;m to&#x1EA1; &#x111;&#x1ED9; uv map d&#x1EF1;a tr&#xEA;n &#x111;i&#x1EC3;m va ch&#x1EA1;m</strong><br>
&#x110;&#x1EA7;u ti&#xEA;n, b&#x1EA1;n c&#x1EA7;n t&#x1EA1;o m&#x1ED9;t RenderTexture. T&#x1EA1;i Project, chu&#x1ED9;t ph&#x1EA3;i ch&#x1ECD;n Create v&#xE0; t&#xEC;m &#x111;&#x1EBF;n ph&#x1EA7;n RenderTexture. &#x110;&#x1EC3; s&#x1EED; d&#x1EE5;ng RenderTexture, ch&#xFA;ng ta s&#x1EBD; c&#x1EA7;n m&#x1ED9;t Camera th&#x1EE9; 2 &#x111;&#x1EC3; ch&#x1EC9; &#x111;&#x1ECB;nh render v&#xE0;o n&#xF3;. Ch&#xFA;ng ta s&#x1EBD; s&#x1EED; d&#x1EE5;ng m&#x1ED9;t Camera v&#x1EDB;i ph&#xE9;p chi&#x1EBF;u tr&#x1EF1;c giao (orthographic projection). T&#x1EA1;i Component Camera, g&#x1EAF;n RenderTexture v&#xE0;o m&#x1EE5;c Target Texture.<br>
T&#x1EA1;o m&#x1ED9;t empty Gameobject v&#xE0; g&#xE1;n script <strong>PaintingTexture.cs</strong>:</p>
<pre><code>public Camera canvasCam;
private Vector2 uvCoord;
private bool HitTestUVPosition(ref Vector3 uvWorldPosition)
{
    if (uvCoord != Vector2.zero)
    {
        uvWorldPosition.x = uvCoord.x - canvasCam.orthographicSize;//To center the UV on X
        uvWorldPosition.y = uvCoord.y - canvasCam.orthographicSize;//To center the UV on Y
        uvWorldPosition.z = 0.0f;
        return true;
    }
    else return false;
}

public void SetUVCoordCollider(Vector2 _uvCoord)
{
    uvCoord = _uvCoord;
}
</code></pre>
<p>H&#xE0;m <strong>HitTestUVPosition()</strong> s&#x1EBD; tr&#x1EA3; v&#x1EC1; to&#x1EA1; &#x111;&#x1ED9; uv map t&#x1EEB; to&#x1EA1; &#x111;&#x1ED9; uv c&#x1EE7;a texture t&#x1EA1;i n&#x1A1;i va ch&#x1EA1;m.<br>
Quay tr&#x1EDF; l&#x1EA1;i script <strong>PhysicsDeformer.cs</strong>, ch&#xFA;ng ta s&#x1EBD; vi&#x1EBF;t ti&#x1EBF;p code &#x111;&#x1EC3; t&#xED;nh to&#xE1;n to&#x1EA1; &#x111;&#x1ED9; uv c&#x1EE7;a texture t&#x1EA1;i n&#x1A1;i va ch&#x1EA1;m:</p>
<pre><code>private void OnCollisionEnter(Collision collision)
{
    if (collision.gameObject.CompareTag(&quot;Terrain&quot;))
    {
        ContactPoint[] contacts = collision.contacts;
        foreach(ContactPoint contact in contacts)
        {
            deformableMesh.AddDepression(contact.point, collisionRadius);
        }
        Vector3 minusNormal = collision.contacts[0].normal;
        minusNormal.y = -collision.contacts[0].normal.y;
        Ray ray = new Ray(collisionTerrainPoint + collision.contacts[0].normal * 0.01f, minusNormal);
        RaycastHit hit;
        if (Physics.Raycast(ray, out hit, 10f, LayerMask.GetMask(&quot;Terrain&quot;)))
        {
            paintScript.SetUVCoordCollider(hit.textureCoord);
        }
    }
}
</code></pre>
<p><strong>2. T&#xF4; m&#xE0;u l&#xEA;n texture runtime d&#x1EF1;a tr&#xEA;n RenderTexture</strong><br>
K&#xE9;o texture c&#x1EE7;a Terrain v&#xE0;o ph&#x1EA1;m vi render c&#x1EE7;a orthogaphic Camera, scale n&#xF3; sao cho k&#xED;ch th&#x1B0;&#x1EDB;c c&#x1EE7;a n&#xF3; v&#x1EEB;a b&#x1EB1;ng ph&#x1EA1;m vi render c&#x1EE7;a orthographic Camera.<br>
T&#x1EA1;o m&#x1ED9;t empty Gameobject, &#x111;&#x1EB7;t t&#xEA;n l&#xE0; <strong>&quot;BrushContainer&quot;</strong>, sau &#x111;&#xF3; k&#xE9;o n&#xF3; &#x1EDF; gi&#x1EEF;a camera v&#xE0; texture c&#x1EE7;a Terrain. Gameobject n&#xE0;y s&#x1EBD; l&#xE0; n&#x1A1;i ch&#x1EE9;a c&#xE1;c gameobject m&#xE0;u m&#xE0; ch&#xFA;ng ta s&#x1EBD; t&#xF4; l&#xEA;n Terrain nh&#x1B0; h&#xEC;nh sau:<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/09/2018-09-05_14-26-42.jpg" alt="[Unity] H&#x1B0;&#x1EDB;ng d&#x1EAB;n l&#xE0;m bi&#x1EBF;n d&#x1EA1;ng v&#xE0; t&#xF4; m&#xE0;u mesh (Deform &amp; paint color on mesh) runtime tr&#xEA;n mobile (p2)" loading="lazy"><br>
&#x110;&#x1EC3; t&#xF4; m&#xE0;u l&#xEA;n texture, ch&#xFA;ng ta s&#x1EBD; s&#x1EED; d&#x1EE5;ng 1 sprite nh&#x1B0; m&#x1ED9;t brush, v&#xE0; t&#x1EA1;o c&#xE1;c brush t&#x1EA1;i v&#x1ECB; tr&#xED; uv map ch&#xFA;ng ta &#x111;&#xE3; l&#x1EA5;y &#x111;&#x1B0;&#x1EE3;c b&#xEA;n tr&#xEA;n. C&#xE1;c brush s&#x1EBD; l&#xE0; c&#xE1;c object con c&#x1EE7;a <strong>BrushContainer</strong>. Khi camera render l&#xEA;n RenderTexture, c&#xE1;c brush s&#x1EBD; n&#x1EB1;m &#x111;&#xE8; l&#xEA;n texture v&#xE0; k&#x1EBF;t qu&#x1EA3; c&#x1EE7;a RenderTexture s&#x1EBD; gi&#x1ED1;ng nh&#x1B0; trong Camera Review ch&#xFA;ng ta nh&#xEC;n th&#x1EA5;y &#x1EDF; h&#xEC;nh &#x1EA3;nh tr&#xEA;n.<br>
&#x110;&#x1EC3; th&#x1EA5;y &#x111;&#x1B0;&#x1EE3;c k&#x1EBF;t qu&#x1EA3;, b&#x1EA1;n h&#xE3;y g&#xE1;n RenderTexture t&#x1EA1;i material c&#x1EE7;a Terrain.<br>
C&#xE1;c b&#x1EA1;n c&#xF3; th&#x1EC3; t&#x1EA3;i brush ho&#x1EB7;c t&#xEC;m ki&#x1EBF;m c&#xE1;c h&#xEC;nh &#x1EA3;nh t&#x1B0;&#x1A1;ng t&#x1EF1;.<br>
<a href="https://drive.google.com/file/d/1SzGraDkKj-gwQGJViLy_5NAzwsgO4B5g/view?usp=sharing&amp;ref=blog.arrow-tech.vn">T&#x1EA3;i h&#xEC;nh brush</a><br>
K&#xE9;o h&#xEC;nh &#x1EA3;nh brush v&#xE0;o scene v&#xE0; t&#x1EA1;o prefab cho n&#xF3;, sau &#x111;&#xF3; xo&#xE1; h&#xEC;nh &#x1EA3;nh brush tr&#xEA;n. Ch&#xFA;ng ta s&#x1EBD; t&#x1EA1;o brush t&#x1EEB; prefab &#x111;&#xF3;. &#x110;&#x1EB7;t prefab v&#xE0;o trong th&#x1B0; m&#x1EE5;c <strong>Resources</strong>.<br>
&#x110;&#x1EC3; t&#x1EA1;o c&#xE1;c brush, h&#xE3;y quay l&#x1EA1;i script <strong>PaintingTexture.cs</strong> v&#xE0; th&#xEA;m c&#xE1;c d&#xF2;ng sau:</p>
<pre><code>public GameObject brushContainer; //our container for the brushes painted
public float brushSize = 1.0f;
public Color brushColor = Color.grey;
private Object resourceBrush;

void Start()
{
    resourceBrush = Resources.Load(&quot;BrushEntity&quot;); // &#x111;&#x1ECB;a ch&#x1EC9; sau th&#x1B0; m&#x1EE5;c Resources/T&#xEA;n object.
}

void InstantiateNewBrush(Vector2 _uvWorldPos)
{
    GameObject brushObj;
    brushObj = (GameObject)Instantiate(resourceBrush); //Paint a brush
    brushObj.GetComponent&lt;SpriteRenderer&gt;().color = brushColor; //Set the brush color
    brushColor.a = brushSize * 2.0f; // Brushes have alpha to have a merging effect when painted over.
    brushObj.transform.parent = brushContainer.transform; //Add the brush to our container to be wiped later
    brushObj.transform.localPosition = _uvWorldPos; //The position of the brush (in the UVMap)
    brushObj.transform.localScale = Vector3.one * brushSize;//The size of the brush
}
</code></pre>
<p>&#x110;&#xE2;y l&#xE0; h&#xE0;m sinh c&#xE1;c brush t&#x1EA1;i v&#x1ECB; tr&#xED; uv map ch&#xFA;ng ta c&#xF3; &#x111;&#x1B0;&#x1EE3;c &#x1EDF; m&#x1EE5;c 1. Ch&#xFA;ng ta c&#xF3; th&#x1EC3; set m&#xE0;u v&#xE0; k&#xED;ch th&#x1B0;&#x1EDB;c brush t&#x1EA1;i inspector.<br>
Tuy nhi&#xEA;n, ch&#xFA;ng ta c&#x1EA7;n ph&#x1EA3;i l&#x1B0;u &#xFD; khi sinh c&#xE0;ng nhi&#x1EC1;u object, s&#x1ED1; l&#x1B0;&#x1EE3;ng draw call s&#x1EBD; r&#x1EA5;t l&#x1EDB;n, &#x111;i&#x1EC1;u n&#xE0;y s&#x1EBD; &#x1EA3;nh h&#x1B0;&#x1EDF;ng kh&#xE1; nhi&#x1EC1;u &#x111;&#x1EBF;n hi&#x1EC7;u n&#x103;ng. &#x110;&#x1EC3; gi&#x1EA3;i quy&#x1EBF;t n&#xF3;, ch&#xFA;ng ta s&#x1EBD; c&#x1EA7;n gi&#x1EDB;i h&#x1EA1;n s&#x1ED1; l&#x1B0;&#x1EE3;ng brush. Ti&#x1EBF;p t&#x1EE5;c trong script <strong>PaintingTexture.cs</strong>, th&#xEA;m c&#xE1;c d&#xF2;ng sau:</p>
<pre><code>public RenderTexture canvasTexture; // Render Texture that looks at our Base Texture and the painted brushes
public Material baseMaterial; // The material of our base texture (Were we will save the painted texture)
private bool saving;
private int brushCounter = 0;

void Start()
{
    resourceBrush = Resources.Load(&quot;BrushEntity&quot;); // &#x111;&#x1ECB;a ch&#x1EC9; sau th&#x1B0; m&#x1EE5;c Resources/T&#xEA;n object.
    baseMaterial.mainTexture = canvasTexture;
}

//Sets the base material with a our canvas texture, then removes all our brushes
void SaveTexture()
{
    brushCounter = 0;
    RenderTexture.active = canvasTexture;
    Texture2D tex = new Texture2D(canvasTexture.width, canvasTexture.height, TextureFormat.RGB24, false);
    tex.ReadPixels(new Rect(0, 0, canvasTexture.width, canvasTexture.height), 0, 0);
    tex.Apply();
    RenderTexture.active = null;
    baseMaterial.mainTexture = tex; //Put the painted texture as the base
    foreach (Transform child in brushContainer.transform)
    {//Clear brushes
        Destroy(child.gameObject);
    }
    Invoke(&quot;ResetTexture&quot;, 0.1f);
}

void ResetTexture()
{
    saving = false;
}
</code></pre>
<p>Cu&#x1ED1;i c&#xF9;ng, s&#x1EED; d&#x1EE5;ng c&#xE1;c h&#xE0;m ch&#x1EE9;c n&#x103;ng b&#xEA;n tr&#xEA;n &#x111;&#x1EC3; t&#xF4; m&#xE0;u t&#x1EA1;i v&#x1ECB; tr&#xED; l&#xE0;m l&#xF5;m:</p>
<pre><code>const int MAX_BRUSH_COUNT = 1000;
void PaintColor()
{
    if (saving)
        return;
    Vector3 uvWorldPosition = Vector3.zero;
    if (HitTestUVPosition(ref uvWorldPosition))
    {
        InstantiateNewBrush(uvWorldPosition);
    }
    brushCounter++; //Add to the max brushes
    if (brushCounter &gt;= MAX_BRUSH_COUNT)
    { //If we reach the max brushes available, flatten the texture and clear the brushes
        saving = true;
        Invoke(&quot;SaveTexture&quot;, 0.1f);
}
</code></pre>
<p>B&#x1EA1;n c&#xF3; th&#x1EC3; gi&#x1EDB;i h&#x1EA1;n s&#x1ED1; l&#x1B0;&#x1EE3;ng brush. T&#x1EA1;i h&#xE0;m <strong>Update()</strong> h&#xE3;y g&#x1ECD;i h&#xE0;m <strong>PaintColor()</strong> &#x111;&#x1EC3; th&#x1EF1;c hi&#x1EC7;n t&#xF4; m&#xE0;u t&#x1EA1;i real time. Tuy nhi&#xEA;n, tu&#x1EF3; thu&#x1ED9;c v&#xE0;o target device c&#x1EE7;a b&#x1EA1;n, h&#xE3;y gi&#x1EDB;i h&#x1EA1;n t&#x1EA7;n su&#x1EA5;t g&#x1ECD;i h&#xE0;m <strong>PaintColor()</strong>.</p>
<h2 id="updatelicolliderchomeshcaterrain">Update l&#x1EA1;i collider cho mesh c&#x1EE7;a Terrain</h2>
<p>Sau khi l&#xE0;m l&#xF5;m v&#xE0; t&#xF4; m&#xE0;u Terrain, ch&#xFA;ng ta c&#x1EA7;n update l&#x1EA1;i collider cho mesh c&#x1EE7;a Terrain. &#x110;&#x1EC3; update l&#x1EA1;i collider, quay tr&#x1EDF; l&#x1EA1;i h&#xE0;m <strong>DeformableMesh.cs</strong> v&#xE0; th&#xEA;m c&#xE1;c d&#xF2;ng sau:</p>
<pre><code>private MeshCollider meshCollider;

void Start()
{
    meshCollider = GetComponent&lt;MeshCollider&gt;();
    MeshRegenerated();
}

void Update()
{
    if(updateCollider)
    {
        timeUpdate += Time.deltaTime;
    }
    if(timeUpdate &gt;3)
    {
        UpdateMeshCollider();
        updateCollider = false;
        timeUpdate = 0;
    }
}

private void UpdateMeshCollider()
{
    meshCollider.sharedMesh = null;
    meshCollider.sharedMesh = meshFilter.mesh;
}
</code></pre>
<p>C&#xF4;ng vi&#x1EC7;c th&#x1EF1;c hi&#x1EC7;n update l&#x1EA1;i mesh collider kh&#xE1; t&#x1ED1;n t&#xE0;i nguy&#xEA;n. Do v&#x1EAD;y, vi&#x1EC7;c n&#xE0;y kh&#xF4;ng th&#x1EC3; &#x111;&#x1B0;&#x1EE3;c th&#x1EF1;c hi&#x1EC7;n m&#x1ED9;t c&#xE1;ch th&#x1B0;&#x1EDD;ng xuy&#xEA;n v&#xE0; ch&#xFA;ng ta c&#x169;ng n&#xEA;n tr&#xE1;nh g&#x1ECD;i n&#xF3; c&#xF9;ng l&#xFA;c v&#x1EDB;i c&#xE1;c c&#xF4;ng vi&#x1EC7;c l&#xE0;m l&#xF5;m v&#xE0; t&#xF4; m&#xE0;u.<br>
Cu&#x1ED1;i c&#xF9;ng, th&#xEA;m d&#xF2;ng</p>
<pre><code>updateCollider = true;
</code></pre>
<p>v&#xE0;o trong h&#xE0;m <strong>AddDepression()</strong> &#x111;&#x1EC3; x&#xE1;c &#x111;&#x1ECB;nh th&#x1EDD;i &#x111;i&#x1EC3;m update mesh collider.</p>
<h2 id="tiliuthamkho">T&#xE0;i li&#x1EC7;u tham kh&#x1EA3;o</h2>
<p><a href="https://codeartist.mx/dynamic-texture-painting/?ref=blog.arrow-tech.vn">https://codeartist.mx/dynamic-texture-painting/</a><br>
<a href="https://www.youtube.com/watch?v=l_2uGpjBMl4&amp;ref=blog.arrow-tech.vn">https://www.youtube.com/watch?v=l_2uGpjBMl4</a></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[[Unity] Hướng dẫn làm biến dạng và tô màu mesh (Deform & paint color on mesh)  runtime trên mobile (p1)]]></title><description><![CDATA[Bài viết này sẽ hướng dẫn cách làm biến dạng mesh trong khi chạy runtime và sử dụng được trên các low-end device. Mình sẽ tạo hiệu ứng lõm Terrain khi xúc đất.]]></description><link>https://blog.arrow-tech.vn/unity-mesh-deformation-bien-dang-mesh-runtime-tren-mobile/</link><guid isPermaLink="false">63915acd7a2f410001205db4</guid><category><![CDATA[Unity]]></category><dc:creator><![CDATA[Datbq ]]></dc:creator><pubDate>Wed, 05 Sep 2018 03:55:12 GMT</pubDate><media:content url="https://blog.arrow-tech.vn/content/images/2018/09/picture-27.png" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><blockquote>
<img src="https://blog.arrow-tech.vn/content/images/2018/09/picture-27.png" alt="[Unity] H&#x1B0;&#x1EDB;ng d&#x1EAB;n l&#xE0;m bi&#x1EBF;n d&#x1EA1;ng v&#xE0; t&#xF4; m&#xE0;u mesh (Deform &amp; paint color on mesh)  runtime tr&#xEA;n mobile (p1)"><p>B&#xE0;i vi&#x1EBF;t n&#xE0;y s&#x1EBD; h&#x1B0;&#x1EDB;ng d&#x1EAB;n c&#xE1;ch l&#xE0;m bi&#x1EBF;n d&#x1EA1;ng mesh trong khi ch&#x1EA1;y runtime v&#xE0; s&#x1EED; d&#x1EE5;ng &#x111;&#x1B0;&#x1EE3;c tr&#xEA;n c&#xE1;c low-end device. C&#x1EE5; th&#x1EC3;, trong b&#xE0;i vi&#x1EBF;t n&#xE0;y m&#xEC;nh s&#x1EBD; t&#x1EA1;o hi&#x1EC7;u &#x1EE9;ng l&#xF5;m Terrain (c&#xF3; mesh nh&#x1B0; m&#x1ED9;t model 3D - kh&#xF4;ng ph&#x1EA3;i built-in Terrain c&#x1EE7;a Unity) khi x&#xFA;c &#x111;&#x1EA5;t.</p>
</blockquote>
<h2 id="tngquan">T&#x1ED5;ng quan</h2>
<p>&#x110;&#x1EC3; t&#x1EA1;o &#x111;&#x1B0;&#x1EE3;c hi&#x1EC7;u &#x1EE9;ng n&#xE0;y, ch&#xFA;ng ta c&#x1EA7;n ph&#x1EA3;i x&#x1EED; l&#xFD; 3 b&#x1B0;&#x1EDB;c:</p>
<ul>
<li>B&#x1B0;&#x1EDB;c 1: Th&#x1EF1;c hi&#x1EC7;n l&#xE0;m l&#xF5;m mesh khi x&#xFA;c &#x111;&#x1EA5;t.</li>
<li>B&#x1B0;&#x1EDB;c 2: T&#xF4; m&#xE0;u xung quanh v&#x1ECB; tr&#xED; l&#xE0;m l&#xF5;m.<br>
Khi x&#xFA;c &#x111;&#x1EA5;t, n&#x1EC1;n &#x111;&#x1EA5;t b&#xEA;n d&#x1B0;&#x1EDB;i kh&#xF4;ng th&#x1EC3; gi&#x1ED1;ng nh&#x1B0; b&#x1EC1; m&#x1EB7;t &#x111;&#x1EA5;t tr&#x1B0;&#x1EDB;c khi x&#xFA;c &#x111;&#x1B0;&#x1EE3;c.</li>
<li>B&#x1B0;&#x1EDB;c 3: Sau khi l&#xE0;m l&#xF5;m, ch&#xFA;ng ta c&#x1EA7;n ph&#x1EA3;i update l&#x1EA1;i collider cho mesh.<br>
Khi ch&#xFA;ng ta di chuy&#x1EC3;n t&#x1EDB;i khu v&#x1EF1;c b&#x1ECB; l&#xE0;m l&#xF5;m, kh&#xF4;ng th&#x1EC3; &#x111;&#x1EE9;ng nh&#x1B0; tr&#xEA;n &#x111;&#x1EA5;t b&#x1EB1;ng nh&#x1B0; tr&#x1B0;&#x1EDB;c khi x&#xFA;c.</li>
</ul>
<h2 id="thchinlmlmmesh">Th&#x1EF1;c hi&#x1EC7;n l&#xE0;m l&#xF5;m mesh</h2>
<p>T&#x1EA1;o script <strong>DeformableMesh.cs</strong> v&#xE0; g&#x1EAF;n v&#xE0;o Terrain.</p>
<pre><code>public float maximumDepression;
private MeshFilter meshFilter;
private List&lt;Vector3&gt; originalVertices;
private List&lt;Vector3&gt; modifiedVertices;

void Start()
{
    MeshRegenerated();  
}

void MeshRegenerated()
{
    meshFilter = GetComponent&lt;MeshFilter&gt;();
    meshFilter.mesh.MarkDynamic();
    originalVertices = meshFilter.mesh.vertices.ToList();
    modifiedVertices = meshFilter.mesh.vertices.ToList();
}

public void AddDepression(Vector3 depressionPoint, float radius)
{
    var worldPos4 = this.transform.worldToLocalMatrix * depressionPoint;
    var worldPos = new Vector3(worldPos4.x, worldPos4.y, worldPos4.z);
    for (int i = 0; i &lt; modifiedVertices.Count; ++i)
    {
        var distance = (worldPos - (modifiedVertices[i] + Vector3.down * maximumDepression)).magnitude;
        if (distance &lt; radius)
        {
            var newVert = originalVertices[i] + Vector3.down * maximumDepression;
            modifiedVertices.RemoveAt(i);
            modifiedVertices.Insert(i, newVert);
        }
    }
    meshFilter.mesh.SetVertices(modifiedVertices);
}
</code></pre>
<p>Trong &#x111;&#xF3;, <strong>maximumDepression</strong> l&#xE0; &#x111;&#x1ED9; s&#xE2;u l&#x1EDB;n nh&#x1EA5;t m&#xE0; mesh b&#x1ECB; bi&#x1EBF;n d&#x1EA1;ng.<br>
B&#x1EA3;n ch&#x1EA5;t c&#x1EE7;a h&#xE0;m <strong>Addpression()</strong> l&#xE0; duy&#x1EC7;t qua list t&#x1EA5;t c&#x1EA3; c&#xE1;c &#x111;&#x1EC9;nh c&#x1EE7;a mesh, sau &#x111;&#xF3; t&#xED;nh to&#xE1;n c&#xE1;c &#x111;&#x1EC9;nh n&#xE0;o s&#x1EBD; b&#x1ECB; bi&#x1EBF;n d&#x1EA1;ng d&#x1EF1;a tr&#xEA;n &#x111;i&#x1EC3;m va ch&#x1EA1;m depressionPoint, radius v&#xE0; c&#x1EAD;p nh&#x1EAD;t l&#x1EA1;i d&#x1EEF; li&#x1EC7;u &#x111;&#x1EC9;nh c&#x1EE7;a mesh. Do v&#x1EAD;y, &#x1EA3;nh h&#x1B0;&#x1EDF;ng c&#x1EE7;a script n&#xE0;y &#x111;&#x1EBF;n hi&#x1EC7;u n&#x103;ng c&#x1EE7;a &#x1EE9;ng d&#x1EE5;ng s&#x1EBD; ph&#x1EE5; thu&#x1ED9;c v&#xE0;o t&#x1EA7;n su&#x1EA5;t n&#xF3; &#x111;&#x1B0;&#x1EE3;c g&#x1ECD;i v&#xE0; s&#x1ED1; &#x111;&#x1EC9;nh c&#x1EE7;a Terrain. Terrain c&#xE0;ng ph&#x1EE9;c t&#x1EA1;p th&#xEC; &#x1EA3;nh h&#x1B0;&#x1EDF;ng c&#x1EE7;a n&#xF3; &#x111;&#x1EBF;n hi&#x1EC7;u n&#x103;ng c&#xE0;ng l&#x1EDB;n. V&#xEC; v&#x1EAD;y, b&#x1EA1;n s&#x1EBD; c&#x1EA7;n ph&#x1EA3;i ch&#xFA; &#xFD; &#x111;&#x1EBF;n s&#x1ED1; verts c&#x1EE7;a Terrain v&#xE0; t&#xEC;m c&#xE1;c c&#xE1;ch &#x111;&#x1EC3; gi&#x1EA3;m thi&#x1EC3;u n&#xF3;.</p>
<p>Ti&#x1EBF;p theo, t&#x1EA1;o script <strong>PhysicsDeformer.cs</strong> v&#xE0; g&#x1EAF;n v&#xE0;o object va ch&#x1EA1;m v&#x1EDB;i Terrain m&#xE0; c&#x1EA7;n t&#x1EA1;o hi&#x1EC7;u &#x1EE9;ng n&#xE0;y.</p>
<pre><code>public float collisionRadius = 0.1f;
public DeformableMesh deformableMesh;
private void OnCollisionEnter(Collision collision)
{
    if (collision.gameObject.CompareTag(&quot;Terrain&quot;))
    {
        ContactPoint[] contacts = collision.contacts;
        foreach(ContactPoint contact in contacts)
        {
            deformableMesh.AddDepression(contact.point, collisionRadius);
        }
    }
}
</code></pre>
<p>Script n&#xE0;y &#x111;&#x1A1;n gi&#x1EA3;n l&#xE0; t&#xEC;m &#x111;i&#x1EC3;m va ch&#x1EA1;m gi&#x1EEF;a object g&#x1EAF;n n&#xF3; v&#xE0; Terrain. <strong>collisionRadius</strong> s&#x1EBD; quy&#x1EBF;t &#x111;&#x1ECB;nh b&#xE1;n k&#xED;nh l&#xE0;m l&#xF5;m t&#x1EA1;i &#x111;i&#x1EC3;m va ch&#x1EA1;m ( s&#x1ED1; l&#x1B0;&#x1EE3;ng c&#xE1;c &#x111;&#x1EC9;nh b&#x1ECB; l&#xE0;m l&#xF5;m xung quanh &#x111;i&#x1EC3;m va ch&#x1EA1;m). V&#x1EDB;i s&#x1ED1; l&#x1B0;&#x1EE3;ng contact c&#xE0;ng l&#x1EDB;n, t&#x1EA7;n su&#x1EA5;t g&#x1ECD;i h&#xE0;m <strong>AddDepression()</strong> c&#xE0;ng nhi&#x1EC1;u. Do v&#x1EAD;y, tu&#x1EF3; theo target device c&#x1EE7;a b&#x1EA1;n m&#xE0; tu&#x1EF3; ch&#x1EC9;nh t&#x1EA7;n su&#x1EA5;t g&#x1ECD;i h&#xE0;m. &#x110;&#x1ED1;i v&#x1EDB;i c&#xE1;c low-end device, b&#x1EA1;n c&#xF3; th&#x1EC3; ch&#x1EC9; g&#x1ECD;i h&#xE0;m 1 l&#x1EA7;n b&#x1EB1;ng thay <strong>contact.point = collision.contacts[0].point</strong> ( &#x111;i&#x1EC3;m va ch&#x1EA1;m &#x111;&#x1EA7;u ti&#xEA;n).</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Continuous Integration với Jenkins & Docker (P1)]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>B&#xE0;i vi&#x1EBF;t n&#xE0;y gi&#x1EDB;i thi&#x1EC7;u m&#xF4; h&#xEC;nh t&#x1EF1; &#x111;&#x1ED9;ng ho&#xE1; trong vi&#x1EC7;c ph&#xE1;t tri&#x1EC3;n ph&#x1EA7;n m&#x1EC1;m b&#x1EB1;ng c&#xE1;ch s&</p>]]></description><link>https://blog.arrow-tech.vn/continuous-integration-voi-jenkins-docker/</link><guid isPermaLink="false">63915acd7a2f410001205db3</guid><dc:creator><![CDATA[honglm]]></dc:creator><pubDate>Mon, 20 Aug 2018 04:14:44 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>B&#xE0;i vi&#x1EBF;t n&#xE0;y gi&#x1EDB;i thi&#x1EC7;u m&#xF4; h&#xEC;nh t&#x1EF1; &#x111;&#x1ED9;ng ho&#xE1; trong vi&#x1EC7;c ph&#xE1;t tri&#x1EC3;n ph&#x1EA7;n m&#x1EC1;m b&#x1EB1;ng c&#xE1;ch s&#x1EED; d&#x1EE5;ng Jenkins v&#xE0; Docker</p>
<h1 id="igiithiuchung">I. Gi&#x1EDB;i thi&#x1EC7;u chung</h1>
<h2 id="11tchhplintccontinuousintegration">1.1. T&#xED;ch h&#x1EE3;p li&#xEA;n t&#x1EE5;c (Continuous Integration)</h2>
<p><em>Continuous Integration l&#xE0; ph&#x1B0;&#x1A1;ng ph&#xE1;p ph&#xE1;t tri&#x1EC3;n ph&#x1EA7;n m&#x1EC1;m y&#xEA;u c&#x1EA7;u c&#xE1;c th&#xE0;nh vi&#xEA;n c&#x1EE7;a team t&#xED;ch h&#x1EE3;p c&#xF4;ng vi&#x1EC7;c c&#x1EE7;a h&#x1ECD; th&#x1B0;&#x1EDD;ng xuy&#xEA;n, m&#x1ED7;i ng&#xE0;y &#xED;t nh&#x1EA5;t m&#x1ED9;t l&#x1EA7;n. M&#x1ED7;i t&#xED;ch h&#x1EE3;p &#x111;&#x1B0;&#x1EE3;c &quot;build&quot; t&#x1EF1; &#x111;&#x1ED9;ng (bao g&#x1ED3;m c&#x1EA3; test) nh&#x1EB1;m ph&#xE1;t hi&#x1EC7;n l&#x1ED7;i nhanh nh&#x1EA5;t c&#xF3; th&#x1EC3;. C&#x1EA3; team nh&#x1EAD;n th&#x1EA5;y r&#x1EB1;ng c&#xE1;ch ti&#x1EBF;p c&#x1EAD;n n&#xE0;y gi&#x1EA3;m thi&#x1EC3;u v&#x1EA5;n &#x111;&#x1EC1; t&#xED;ch h&#x1EE3;p v&#xE0; cho ph&#xE9;p ph&#xE1;t tri&#x1EC3;n ph&#x1EA7;n m&#x1EC1;m nhanh h&#x1A1;n.</em></p>
<p>M&#x1ED9;t k&#x1ECB;ch b&#x1EA3;n CI b&#x1EAF;t &#x111;&#x1EA7;u b&#x1EB1;ng vi&#x1EC7;c developer commit code l&#xEA;n repository (github ch&#x1EB3;ng h&#x1EA1;n). B&#x1EA5;t k&#x1EF3; thay &#x111;&#x1ED5;i n&#xE0;o c&#x169;ng s&#x1EBD; trigger m&#x1ED9;t v&#xF2;ng &#x111;&#x1EDD;i CI. C&#xE1;c b&#x1B0;&#x1EDB;c trong m&#x1ED9;t k&#x1ECB;ch b&#x1EA3;n CI th&#x1B0;&#x1EDD;ng nh&#x1B0; sau:</p>
<ul>
<li>&#x110;&#x1EA7;u ti&#xEA;n, developer commit code l&#xEA;n repo.</li>
<li>CI server gi&#xE1;m s&#xE1;t repo v&#xE0; ki&#x1EC3;m tra xem li&#x1EC7;u c&#xF3; thay &#x111;&#x1ED5;i n&#xE0;o tr&#xEA;n repo hay kh&#xF4;ng (li&#xEA;n t&#x1EE5;c, ch&#x1EB3;ng h&#x1EA1;n m&#x1ED7;i ph&#xFA;t 1 l&#x1EA7;n)</li>
<li>Ngay khi commit x&#x1EA3;y ra, CI server ph&#xE1;t hi&#x1EC7;n repo c&#xF3; thay &#x111;&#x1ED5;i, n&#xEA;n n&#xF3; nh&#x1EAD;n code m&#x1EDB;i nh&#x1EA5;t t&#x1EEB; repo v&#xE0; sau &#x111;&#xF3; build, ch&#x1EA1;y unit v&#xE0; integration test</li>
<li>CI server s&#x1EBD; sinh ra c&#xE1;c feedback v&#xE0; g&#x1EED;i &#x111;&#x1EBF;n c&#xE1;c member c&#x1EE7;a project</li>
<li>CI server ti&#x1EBF;p t&#x1EE5;c ch&#x1EDD; thay &#x111;&#x1ED5;i &#x1EDF; repo<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/08/ci.png" alt="ci" loading="lazy"></li>
</ul>
<p>M&#x1ED7;i l&#x1EA7;n developer l&#xE0;m xong task, h&#x1ECD; ph&#x1EA3;i ch&#x1EA1;y m&#x1ED9;t private build (t&#x1EE9;c l&#xE0; ch&#x1EA1;y ph&#x1EA7;n m&#x1EC1;m tr&#xEA;n local tr&#x1B0;&#x1EDB;c), check c&#x1EA9;n th&#x1EAD;n v&#xE0; commit code l&#xEA;n repo khi &#x111;&#xE3; th&#x1EA5;y &#x1ED5;n. B&#x1B0;&#x1EDB;c n&#xE0;y x&#x1EA3;y ra th&#x1B0;&#x1EDD;ng xuy&#xEA;n v&#xE0; &#x1EDF; b&#x1EA5;t k&#x1EF3; th&#x1EDD;i &#x111;i&#x1EC3;m n&#xE0;o trong ng&#xE0;y. Vi&#x1EC7;c build t&#xED;ch h&#x1EE3;p s&#x1EBD; kh&#xF4;ng x&#x1EA3;y ra khi nh&#x1EEF;ng thay &#x111;&#x1ED5;i n&#xE0;y ch&#x1B0;a &#x1EA3;nh h&#x1B0;&#x1EDF;ng &#x111;&#x1EBF;n repo.</p>
<p>L&#x1EE3;i &#xED;ch c&#x1EE7;a vi&#x1EC7;c s&#x1EED; d&#x1EE5;ng CI l&#xE0;:</p>
<ul>
<li><strong>Gi&#x1EA3;m thi&#x1EC3;u r&#x1EE7;i ro</strong> nh&#x1EDD; vi&#x1EC7;c ph&#xE1;t hi&#x1EC7;n l&#x1ED7;i v&#xE0; fix s&#x1EDB;m, t&#x103;ng ch&#x1EA5;t l&#x1B0;&#x1EE3;ng ph&#x1EA7;n m&#x1EC1;m nh&#x1EDD; vi&#x1EC7;c t&#x1EF1; &#x111;&#x1ED9;ng test v&#xE0; inspect (&#x111;&#xE2;y c&#x169;ng l&#xE0; m&#x1ED9;t trong nh&#x1EEF;ng l&#x1EE3;i &#xED;ch c&#x1EE7;a CI, code &#x111;&#x1B0;&#x1EE3;c inspect t&#x1EF1; &#x111;&#x1ED9;ng d&#x1EF1;a theo config &#x111;&#xE3; c&#xE0;i &#x111;&#x1EB7;t, &#x111;&#x1EA3;m b&#x1EA3;o coding style, ch&#x1EB3;ng h&#x1EA1;n m&#x1ED9;t function ch&#x1EC9; &#x111;&#x1B0;&#x1EE3;c d&#xE0;i kh&#xF4;ng qu&#xE1; 10 d&#xF2;ng code ...)</li>
<li><strong>Gi&#x1EA3;m thi&#x1EC3;u nh&#x1EEF;ng quy tr&#xEC;nh th&#x1EE7; c&#xF4;ng</strong> l&#x1EB7;p &#x111;i l&#x1EB7;p l&#x1EA1;i (build css, js, migrate, test...), thay v&#xEC; &#x111;&#xF3; l&#xE0; build t&#x1EF1; &#x111;&#x1ED9;ng, ch&#x1EA1;y test t&#x1EF1; &#x111;&#x1ED9;ng</li>
<li>Sinh ra ph&#x1EA7;n m&#x1EC1;m c&#xF3; th&#x1EC3; <strong>deploy &#x1EDF; b&#x1EA5;t k&#xEC; th&#x1EDD;i gian</strong>, &#x111;&#x1ECB;a &#x111;i&#x1EC3;m</li>
</ul>
<h2 id="12jenkins">1.2. Jenkins</h2>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/08/jenkin.png" alt="jenkin" loading="lazy"></p>
<p><em>Jenkins l&#xE0; m&#x1ED9;t ph&#x1EA7;n m&#x1EC1;m t&#x1EF1; &#x111;&#x1ED9;ng h&#xF3;a, m&#xE3; ngu&#x1ED3;n m&#x1EDF; v&#xE0; vi&#x1EBF;t b&#x1EB1;ng Java. Jenkins gi&#xFA;p t&#x1EF1; &#x111;&#x1ED9;ng h&#xF3;a c&#xE1;c quy tr&#xEC;nh trong ph&#xE1;t tri&#x1EC3;n ph&#x1EA7;n m&#x1EC1;m, hi&#x1EC7;n nay &#x111;&#x1B0;&#x1EE3;c d&#xF9;ng trong T&#xED;ch h&#x1EE3;p li&#xEA;n t&#x1EE5;c, v&#xE0; c&#xF2;n &#x111;&#x1B0;&#x1EE3;c d&#xF9;ng &#x111;&#x1EBF;n trong vi&#x1EC7;c Ph&#xE2;n ph&#x1ED1;i li&#xEA;n t&#x1EE5;c.</em></p>
<p>Jenkins h&#x1ED7; tr&#x1EE3; h&#x1EA7;u h&#x1EBF;t c&#xE1;c ph&#x1EA7;n m&#x1EC1;m qu&#x1EA3;n l&#xFD; m&#xE3; ngu&#x1ED3;n ph&#x1ED5; bi&#x1EBF;n hi&#x1EC7;n nay nh&#x1B0; Git, Subversion, Mercurial, ClearCase... Jenkins c&#x169;ng h&#x1ED7; tr&#x1EE3; c&#x1EA3; c&#xE1;c m&#xE3; l&#x1EC7;nh c&#x1EE7;a Shell v&#xE0; Windows Batch, &#x111;&#x1ED3;ng th&#x1EDD;i c&#xF2;n ch&#x1EA1;y &#x111;&#x1B0;&#x1EE3;c c&#xE1;c m&#xE3; l&#x1EC7;nh c&#x1EE7;a Apache Ant, Maven, Gradle... [wiki-site]</p>
<p>Plugin l&#xE0; c&#xE1;c ph&#x1EA7;n m&#x1EDF; r&#x1ED9;ng trong Jenkins, h&#x1ED7; tr&#x1EE3; c&#xE1;c d&#x1EF1; &#xE1;n kh&#xF4;ng d&#xF9;ng ng&#xF4;n ng&#x1EEF; Java. Plugin c&#xF3; th&#x1EC3; t&#xED;ch h&#x1EE3;p h&#x1EA7;u h&#x1EBF;t c&#xE1;c h&#x1EC7; th&#x1ED1;ng qu&#x1EA3;n l&#xFD; m&#xE3; ngu&#x1ED3;n v&#xE0; c&#x1A1; s&#x1EDF; d&#x1EEF; li&#x1EC7;u v&#xE0;o Jenkins. Nhi&#x1EC1;u c&#xF4;ng c&#x1EE5; build c&#xF3; plugin ri&#xEA;ng. Plugin c&#x169;ng c&#xF3; th&#x1EC3; thay &#x111;&#x1ED5;i giao di&#x1EC7;n ho&#x1EB7;c th&#xEA;m ch&#x1EE9;c n&#x103;ng m&#x1EDB;i cho Jenkins. Nhi&#x1EC1;u plugin d&#xE0;nh ri&#xEA;ng cho c&#xE1;c m&#x1EE5;c &#x111;&#xED;ch kh&#xE1;c nhau.</p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/08/jenkin_build.png" alt="jenkin_build" loading="lazy"></p>
<h2 id="13docker">1.3. Docker</h2>
<p><em>Docker l&#xE0; m&#x1ED9;t ph&#x1EA7;n m&#x1EC1;m cung c&#x1EA5;p m&#xF4;i tr&#x1B0;&#x1EDD;ng &#x1EA3;o h&#xF3;a ch&#x1EE9;a &#x111;&#x1EA7;y &#x111;&#x1EE7; c&#xE0;i &#x111;&#x1EB7;t c&#x1EA7;n thi&#x1EBF;t cho project. Docker gi&#xFA;p t&#x103;ng t&#x1ED1;c &#x111;&#x1ED9; x&#xE2;y d&#x1EF1;ng project v&#xE0; gi&#x1EA3;m thi&#x1EC3;u l&#x1ED7;i khi chuy&#x1EC3;n giao. Hi&#x1EC7;n nay docker &#x111;ang tr&#x1EDF; n&#xEA;n r&#x1EA5;t ph&#x1ED5; bi&#x1EBF;n.</em></p>
<p>C&#xE1;c v&#x1EA5;n &#x111;&#x1EC1; c&#x1EA7;n t&#xEC;m hi&#x1EC3;u:<br>
-Image<br>
-Container<br>
-Registry<br>
-Repository<br>
-Docker hub</p>
<h2 id="14mhnhcbn">1.4. M&#xF4; h&#xEC;nh c&#x1A1; b&#x1EA3;n</h2>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/08/mohinhcoban.png" alt="mohinhcoban" loading="lazy"><br>
M&#xF4; t&#x1EA3;:</p>
<ul>
<li>Khi dev push code l&#xEA;n Gitlab, Gitlab s&#x1EBD; g&#x1ECD;i m&#x1ED9;t webhook th&#xF4;ng b&#xE1;o cho Jenkins bi&#x1EBF;t c&#xF3; s&#x1EF1; ki&#x1EC7;n push code.</li>
<li>Jenkins b&#x1EAF;t &#x111;&#x1B0;&#x1EE3;c s&#x1EF1; ki&#x1EC7;n n&#xE0;y v&#xE0; ch&#x1EA1;y pipeline. Pipeline &#x111;&#x1B0;&#x1EE3;c m&#xF4; t&#x1EA3; nh&#x1EEF;ng c&#xF4;ng vi&#x1EC7;c m&#xE0; Jenkins c&#x1EA7;n th&#x1EF1;c hi&#x1EC7;n &#x111;&#x1B0;&#x1EE3;c ch&#x1EC9; ra b&#x1EDF;i dev.</li>
<li>Trong m&#xF4; h&#xEC;nh n&#xE0;y, pipeline s&#x1EBD; th&#x1EF1;c hi&#x1EC7;n 4 c&#xF4;ng vi&#x1EC7;c sau:
<ul>
<li>Pull code t&#x1EEB; server</li>
<li>&#x110;&#xF3;ng g&#xF3;i project</li>
<li>Build Docker Image, g&#x1EAF;n tag</li>
<li>Publish Image l&#xEA;n 1 registry</li>
</ul>
</li>
<li>Sau khi ho&#xE0;n t&#x1EA5;t vi&#x1EC7;c publish image l&#xEA;n Docker registry th&#xEC; pipeline s&#x1EBD; k&#x1EBF;t th&#xFA;c. K&#x1EBF;t qu&#x1EA3; tr&#x1EA3; thu &#x111;&#x1B0;&#x1EE3;c l&#xE0;:
<ul>
<li>Image m&#x1EDB;i tr&#xEA;n Registry</li>
<li>Image tr&#xEA;n m&#xE1;y c&#xE0;i &#x111;&#x1EB7;t Docker</li>
</ul>
</li>
</ul>
<h1 id="iiccbccit">II. C&#xE1;c b&#x1B0;&#x1EDB;c c&#xE0;i &#x111;&#x1EB7;t</h1>
<p>Ph&#x1EA7;n n&#xE0;y m&#xEC;nh s&#x1EBD; gi&#x1EDB;i thi&#x1EC7;u &#x1EDF; b&#xE0;i ti&#x1EBF;p theo nh&#xE9;.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Hướng dẫn sử dụng công cụ Vuls để quét lỗ hổng bảo mật trên hệ điều hành nhân *nix (Ubuntu, Debian, RHEL, Oracle Linux, CentOS..)]]></title><description><![CDATA[<!--kg-card-begin: markdown--><h1 id="nidungtrnhby">N&#x1ED9;i dung tr&#xEC;nh b&#xE0;y:</h1>
<ul>
<li>Gi&#x1EDB;i thi&#x1EC7;u</li>
<li>C&#xE0;i &#x111;&#x1EB7;t</li>
<li>Qu&#xE9;t h&#x1EC7; th&#x1ED1;ng</li>
<li>K&#x1EBF;t qu&#x1EA3; qu&#xE9;t</li>
</ul>
<h1 id="giithiu">Gi&#x1EDB;i thi&#x1EC7;u</h1>
<ul>
<li>L&#xE0; c&#xF4;ng c&</li></ul>]]></description><link>https://blog.arrow-tech.vn/vuls/</link><guid isPermaLink="false">63915acd7a2f410001205db1</guid><category><![CDATA[Security]]></category><category><![CDATA[Linux]]></category><dc:creator><![CDATA[dungbv]]></dc:creator><pubDate>Fri, 25 May 2018 08:41:55 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><h1 id="nidungtrnhby">N&#x1ED9;i dung tr&#xEC;nh b&#xE0;y:</h1>
<ul>
<li>Gi&#x1EDB;i thi&#x1EC7;u</li>
<li>C&#xE0;i &#x111;&#x1EB7;t</li>
<li>Qu&#xE9;t h&#x1EC7; th&#x1ED1;ng</li>
<li>K&#x1EBF;t qu&#x1EA3; qu&#xE9;t</li>
</ul>
<h1 id="giithiu">Gi&#x1EDB;i thi&#x1EC7;u</h1>
<ul>
<li>L&#xE0; c&#xF4;ng c&#x1EE5; m&#xE3; ngu&#x1ED3;n m&#x1EDF;, qu&#xE9;t l&#x1ED7; h&#x1ED5;ng b&#x1EA3;o m&#x1EAD;t tr&#xEA;n c&#xE1;c g&#xF3;i ph&#x1EA7;n m&#x1EC1;m &#x111;&#xE3; &#x111;&#x1B0;&#x1EE3;c c&#xE0;i &#x111;&#x1EB7;t tr&#xEA;n OS.</li>
<li>Vuls qu&#xE9;t d&#x1EF1;a tr&#xEA;n th&#xF4;ng tin t&#x1EEB; NVD, OVAL, &#x2026;</li>
<li>Nh&#x1EEF;ng OS &#x111;&#x1B0;&#x1EE3;c support: Alpine, Ubuntu, Debian, RHEL, Oracle Linux, CentOS, SUSE Enterprise, &#x2026;</li>
<li>K&#x1EBF;t qu&#x1EA3; qu&#xE9;t c&#xF3; th&#x1EC3; xem v&#x1EDB;i Terminal Based Viewer ho&#x1EB7;c VulsRepo (Web UI).</li>
<li>Th&#xF4;ng b&#xE1;o k&#x1EBF;t qu&#x1EA3; qu&#xE9;t qua email, slack.<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/05/Screen-Shot-2018-05-25-at-10.56.17-AM.png" alt="Screen-Shot-2018-05-25-at-10.56.17-AM" loading="lazy"></li>
</ul>
<h1 id="cit">C&#xE0;i &#x111;&#x1EB7;t</h1>
<p>Sau &#x111;&#xE2;y l&#xE0; c&#xE1;c b&#x1B0;&#x1EDB;c c&#xE0;i &#x111;&#x1EB7;t tr&#xEA;n Ubuntu</p>
<h2 id="citccyucu">C&#xE0;i &#x111;&#x1EB7;t c&#xE1;c y&#xEA;u c&#x1EA7;u</h2>
<h3 id="package">Package</h3>
<pre><code>$ sudo apt-get install sqlite git gcc make wget
$ wget https://dl.google.com/go/go1.10.2.linux-amd64.tar.gz
$ sudo tar -C /usr/local -xzf go1.10.2.linux-amd64.tar.gz
$ mkdir $HOME/go
</code></pre>
<h3 id="thmexportvoetcprofiledgoenvsh">Th&#xEA;m export v&#xE0;o <code>/etc/profile.d/goenv.sh</code></h3>
<pre><code>export GOROOT=/usr/local/go
export GOPATH=$HOME/go
export PATH=$PATH:$GOROOT/bin:$GOPATH/bin
</code></pre>
<h3 id="setbinmitrngtrnvoshellhinti">Set bi&#x1EBF;n m&#xF4;i tr&#x1B0;&#x1EDD;ng &#x1EDF; tr&#xEA;n v&#xE0;o shell hi&#x1EC7;n t&#x1EA1;i</h3>
<pre><code>$ source /etc/profile.d/goenv.sh
</code></pre>
<h2 id="deploygocvedictionary">Deploy go-cve-dictionary</h2>
<h3 id="buildktquctdigopathbin">Build, k&#x1EBF;t qu&#x1EA3; &#x111;&#x1B0;&#x1EE3;c &#x111;&#x1EB7;t d&#x1B0;&#x1EDB;i <code>$GOPATH/bin</code></h3>
<pre><code>$ sudo mkdir /var/log/vuls
$ sudo chown user_name /var/log/vuls
$ sudo chmod 700 /var/log/vuls

$ mkdir -p $GOPATH/src/github.com/kotakanbe
$ cd $GOPATH/src/github.com/kotakanbe
$ git clone https://github.com/kotakanbe/go-cve-dictionary.git
$ cd go-cve-dictionary
$ make install
</code></pre>
<h3 id="fetchdliutnvd">Fetch d&#x1EEF; li&#x1EC7;u t&#x1EEB; NVD</h3>
<pre><code>$ mkdir $HOME/vuls
$ cd $HOME/vuls
$ for i in `seq 2002 $(date +&quot;%Y&quot;)`; do go-cve-dictionary fetchnvd -years $i; done
</code></pre>
<h2 id="deploygovaldictionary">Deploy goval-dictionary</h2>
<h3 id="buildktquctdigopathbin">Build, k&#x1EBF;t qu&#x1EA3; &#x111;&#x1B0;&#x1EE3;c &#x111;&#x1EB7;t d&#x1B0;&#x1EDB;i <code>$GOPATH/bin</code></h3>
<pre><code>$ mkdir -p $GOPATH/src/github.com/kotakanbe
$ cd $GOPATH/src/github.com/kotakanbe
$ git clone https://github.com/kotakanbe/goval-dictionary.git
$ cd goval-dictionary
$ make install
</code></pre>
<h3 id="fetchdliuoval">Fetch d&#x1EEF; li&#x1EC7;u OVAL</h3>
<p>Ph&#x1EE5; thu&#x1ED9;c v&#xE0;o OS c&#x1EA7;n qu&#xE9;t, chi ti&#x1EBF;t: <a href="https://github.com/kotakanbe/goval-dictionary?ref=blog.arrow-tech.vn">https://github.com/kotakanbe/goval-dictionary</a></p>
<pre><code>$ cd $HOME/vuls
$ goval-dictionary fetch-ubuntu 12 14 16 18 #Ubuntu
</code></pre>
<h2 id="deployvuls">Deploy Vuls</h2>
<pre><code>$ mkdir -p $GOPATH/src/github.com/future-architect
$ cd $GOPATH/src/github.com/future-architect
$ git clone https://github.com/future-architect/vuls.git
$ cd vuls
$ make install
</code></pre>
<h1 id="quththng">Qu&#xE9;t h&#x1EC7; th&#x1ED1;ng</h1>
<p>Vuls h&#x1ED7; tr&#x1EE3; local scan v&#xE0; remote scan. D&#x1B0;&#x1EDB;i &#x111;&#xE2;y l&#xE0; h&#x1B0;&#x1EDB;ng d&#x1EAB;n scan localhost</p>
<pre><code>$ cd $HOME/vuls
# T&#x1EA1;o file config.toml nh&#x1B0; sau:
[servers]
[servers.localhost]
host = &quot;localhost&quot;
port = &quot;local&quot;
</code></pre>
<h3 id="kimtra">Ki&#x1EC3;m tra</h3>
<p>Ki&#x1EC3;m tra config.toml v&#xE0; setting tr&#xEA;n server tr&#x1B0;&#x1EDB;c khi scan</p>
<pre><code>$ vuls configtest
</code></pre>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/05/Screen-Shot-2018-05-25-at-11.52.49-AM.png" alt="Screen-Shot-2018-05-25-at-11.52.49-AM" loading="lazy"></p>
<h3 id="scan">Scan</h3>
<pre><code>$ vuls scan
</code></pre>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/05/Screen-Shot-2018-05-25-at-11.56.29-AM.png" alt="Screen-Shot-2018-05-25-at-11.56.29-AM" loading="lazy"></p>
<h3 id="report">Report</h3>
<pre><code>$ vuls report -format-one-line-text
</code></pre>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/05/Screen-Shot-2018-05-25-at-1.12.12-PM.png" alt="Screen-Shot-2018-05-25-at-1.12.12-PM" loading="lazy"></p>
<pre><code>$ vuls report -format-short-text
$ vuls report -format-full-text | less
</code></pre>
<h1 id="ktququt">K&#x1EBF;t qu&#x1EA3; qu&#xE9;t</h1>
<h2 id="terminalbaseduserinterface">Terminal-Based User Interface</h2>
<pre><code>$ vuls tui
</code></pre>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/05/Screen-Shot-2018-05-25-at-1.18.36-PM.png" alt="Screen-Shot-2018-05-25-at-1.18.36-PM" loading="lazy"></p>
<h2 id="webui">Web UI</h2>
<p>VulsRepo cung c&#x1EA5;p giao di&#x1EC7;n web &#x111;&#x1EC3; th&#x1ECB; k&#x1EBF;t qu&#x1EA3; m&#x1ED9;t c&#xE1;ch tr&#x1EF1;c quan h&#x1A1;n</p>
<h3 id="tomtjsonreportcavulsvclonevulsrepo">T&#x1EA1;o m&#x1ED9;t json report c&#x1EE7;a vuls v&#xE0; clone vulsrepo</h3>
<pre><code>$ cd $HOME/vuls
$ vuls scan 
$ vuls report -format-json 

$ git clone https://github.com/usiusi360/vulsrepo.git
$ cd vulsrepo/server
$ cp vulsrepo-config.toml.sample vulsrepo-config.toml

# N&#x1ED9;i dung file vulsrepo-config.toml
[Server]
rootPath = &#x201C;/home/user_name/vuls/vusrepo&#x201D;
resultsPath = &#x201C;/home/user_name/vuls/results&#x201D;
serverPort = &#x201C;5111&#x201D;
</code></pre>
<h3 id="startvulsreposerver">Start vulsrepo-server</h3>
<pre><code>$ ./vulsrepo-server
</code></pre>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/05/Screen-Shot-2018-05-25-at-1.55.57-PM.png" alt="Screen-Shot-2018-05-25-at-1.55.57-PM" loading="lazy"></p>
<h3 id="mtshnhnhcavulsrepo">M&#x1ED9;t s&#x1ED1; h&#xEC;nh &#x1EA3;nh c&#x1EE7;a vulsrepo</h3>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/05/Screen-Shot-2018-05-25-at-2.00.41-PM.png" alt="Screen-Shot-2018-05-25-at-2.00.41-PM" loading="lazy"></p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/05/Screen-Shot-2018-05-25-at-2.02.16-PM.png" alt="Screen-Shot-2018-05-25-at-2.02.16-PM" loading="lazy"></p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/05/Screen-Shot-2018-05-25-at-2.03.26-PM.png" alt="Screen-Shot-2018-05-25-at-2.03.26-PM" loading="lazy"></p>
<h1 id="thngtinchititxemtihttpsvulsio">Th&#xF4;ng tin chi ti&#x1EBF;t xem t&#x1EA1;i: <a href="https://vuls.io/?ref=blog.arrow-tech.vn">https://vuls.io/</a></h1>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Unity Tool - Sử dụng Mesh Baker để hợp nhất các material và mesh nhằm giảm Draw Call - Tối ưu game Unity]]></title><description><![CDATA[Tối ưu hóa Draw call trong Unity sử dụng mesk baker giảm thiểu tác vụ cho CPU]]></description><link>https://blog.arrow-tech.vn/unity-tool-su-dung-mesh-baker-de-hop-nhat-cac-material-va-mesh-nham-giam-draw-call-toi-uu-game-unity/</link><guid isPermaLink="false">63915acd7a2f410001205db0</guid><category><![CDATA[Unity]]></category><dc:creator><![CDATA[phont]]></dc:creator><pubDate>Fri, 25 May 2018 04:53:05 GMT</pubDate><media:content url="https://blog.arrow-tech.vn/content/images/2018/05/Matthew_school_boy-512.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><h2 id="1giithiu">1. Gi&#x1EDB;i thi&#x1EC7;u</h2>
<img src="https://blog.arrow-tech.vn/content/images/2018/05/Matthew_school_boy-512.jpg" alt="Unity Tool - S&#x1EED; d&#x1EE5;ng Mesh Baker &#x111;&#x1EC3; h&#x1EE3;p nh&#x1EA5;t c&#xE1;c material v&#xE0; mesh nh&#x1EB1;m gi&#x1EA3;m Draw Call - T&#x1ED1;i &#x1B0;u game Unity"><p>T&#x1ED1;i &#x1B0;u h&#xF3;a l&#xE0; m&#x1ED9;t ph&#x1EA7;n quan tr&#x1ECD;ng trong qu&#xE1; tr&#xEC;nh ph&#xE1;t tri&#x1EC3;n game. M&#x1ED7;i n&#x1EC1;n t&#x1EA3;ng ph&#xE1;t tri&#x1EC3;n game &#x111;&#x1EC1;u c&#xF3; nh&#x1EEF;ng h&#x1EA1;n ch&#x1EBF; v&#x1EC1; n&#x103;ng l&#x1EF1;c x&#x1EED; l&#xFD; c&#x1EE7;a GPU v&#xE0; CPU. &#x110;&#x1EB7;c bi&#x1EC7;t trong game 3D v&#x1EDB;i &#x111;&#x1ED9; chi ti&#x1EBF;t cao th&#xEC; nhu c&#x1EA7;u x&#x1EED; l&#xFD; s&#x1EBD; c&#xE0;ng cao. Khi nhu c&#x1EA7;u x&#x1EED; l&#xFD; n&#xE0;y tr&#x1EDF; n&#xEA;n qu&#xE1; t&#x1EA3;i th&#xEC; hi&#x1EC7;u n&#x103;ng game s&#x1EBD; gi&#x1EA3;m. Vi&#x1EC7;c n&#xE0;y t&#x1EA1;o n&#xEA;n c&#x1EA3;m gi&#xE1;c kh&#xF3; ch&#x1ECB;u cho ng&#x1B0;&#x1EDD;i d&#xF9;ng nh&#x1B0; l&#xE0; load game l&#xE2;u, game ch&#x1EA1;y ch&#x1EAD;m v&#xE0; th&#x1EAD;m ch&#xED; b&#x1ECB; treo h&#x1EC7; th&#x1ED1;ng. Quy tr&#xEC;nh t&#x1ED1;i &#x1B0;u h&#xF3;a l&#xE0; chu&#x1ED5;i c&#xE1;c quy&#x1EBF;t &#x111;&#x1ECB;nh gi&#x1EEF;a vi&#x1EC7;c duy tr&#xEC;nh hi&#x1EC7;u n&#x103;ng game v&#xE0; ch&#x1EA5;t l&#x1B0;&#x1EE3;ng &#x111;&#x1ED3; h&#x1ECD;a.</p>
<p>Trong Unity &#x111;&#x1EC3; t&#x1ED1;i &#x1B0;u h&#xF3;a ch&#xFA;ng ta c&#xF3; r&#x1EA5;t nhi&#x1EC1;u ph&#x1B0;&#x1A1;ng &#xE1;n kh&#xE1;c nhau, &#x1EDF; ph&#x1EA1;m vi b&#xE0;i vi&#x1EBF;t n&#xE0;y s&#x1EBD; gi&#x1EDB;i thi&#x1EC7;u c&#xF4;ng c&#x1EE5; Mesk Baker. C&#xF4;ng c&#x1EE5; n&#xE0;y c&#xF3; t&#xE1;c d&#x1EE5;ng h&#x1EE3;p nh&#x1EA5;t c&#xE1;c material v&#xE0; mesh nh&#x1EB1;m gi&#x1EA3;m Draw Call, ngh&#x129;a l&#xE0; gi&#x1EA3;m b&#x1EDB;t c&#xF4;ng vi&#x1EC7;c cho CPU.</p>
<h2 id="2hngdnsdngmeskbaker">2. H&#x1B0;&#x1EDB;ng d&#x1EAB;n s&#x1EED; d&#x1EE5;ng Mesk Baker</h2>
<p><em>Mesk Baker y&#xEA;u c&#x1EA7;u  Unity 4.6 or higher<br>
&#x1EDE; &#x111;&#xE2;y ch&#xFA;ng t&#xF4;i demo tr&#xEA;n Unity 2017</em></p>
<h3 id="acit">a. C&#xE0;i &#x111;&#x1EB7;t</h3>
<p>&#x110;&#x1EC3; s&#x1EED; d&#x1EE5;ng c&#xF4;ng c&#x1EE5; n&#xE0;y b&#x1EA1;n c&#xF3; th&#x1EC3; mua tr&#x1EF1;c ti&#x1EBF;p tr&#xEA;n Asset Store (65$) ho&#x1EB7;c v&#xE0;o website : <a href="http://digitalopus.ca/site/mesh-baker/?ref=blog.arrow-tech.vn">http://digitalopus.ca/site/mesh-baker/</a>  &#x111;&#x1EC3; s&#x1EED; d&#x1EE5;ng b&#x1EA3;n Evaluation Version - mi&#x1EC5;n ph&#xED; nh&#x1B0;ng gi&#x1EDB;i h&#x1EA1;n t&#xED;nh n&#x103;ng.<br>
Sau khi download package MeshBaker ch&#xFA;ng ta import v&#xE0;o unity. Sau khi import th&#xE0;nh c&#xF4;ng ch&#xFA;ng ta s&#x1EBD; c&#xF3; giao di&#x1EC7;n nh&#x1B0; sau</p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/05/1.png" alt="Unity Tool - S&#x1EED; d&#x1EE5;ng Mesh Baker &#x111;&#x1EC3; h&#x1EE3;p nh&#x1EA5;t c&#xE1;c material v&#xE0; mesh nh&#x1EB1;m gi&#x1EA3;m Draw Call - T&#x1ED1;i &#x1B0;u game Unity" loading="lazy"></p>
<h3 id="bsdngmeskbaker">b. S&#x1EED; d&#x1EE5;ng Mesk Baker</h3>
<p>&#x110;&#x1EC3; t&#xEC;m hi&#x1EC3;u th&#xEA;m c&#xE1;ch s&#x1EED; d&#x1EE5;ng Mesk Baker b&#x1EA1;n c&#xF3; th&#x1EC3; t&#xEC;m hi&#x1EC3;u tr&#x1EF1;c ti&#x1EBF;p tr&#xEA;n trang ch&#xED;nh th&#x1EE9;c: <a href="http://digitalopus.ca/site/mesh-baker-videos/?ref=blog.arrow-tech.vn">http://digitalopus.ca/site/mesh-baker-videos/</a><br>
&#x1EDE; &#x111;&#xE2;y ch&#xFA;ng t&#xF4;i s&#x1EBD; gi&#x1EDB;i thi&#x1EC7;u m&#x1ED9;t trong nh&#x1EEF;ng tr&#x1B0;&#x1EDD;ng h&#x1EE3;p c&#x1A1; b&#x1EA3;n nh&#x1EA5;t</p>
<p>B&#x1B0;&#x1EDB;c 1: T&#x1EA1;o m&#x1ED9;t MeskBaker nh&#x1B0; h&#xEC;nh</p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/05/1.png" alt="Unity Tool - S&#x1EED; d&#x1EE5;ng Mesh Baker &#x111;&#x1EC3; h&#x1EE3;p nh&#x1EA5;t c&#xE1;c material v&#xE0; mesh nh&#x1EB1;m gi&#x1EA3;m Draw Call - T&#x1ED1;i &#x1B0;u game Unity" loading="lazy"></p>
<p>Ta &#x111;&#x1B0;&#x1EE3;c</p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/05/2-copy-1.png" alt="Unity Tool - S&#x1EED; d&#x1EE5;ng Mesh Baker &#x111;&#x1EC3; h&#x1EE3;p nh&#x1EA5;t c&#xE1;c material v&#xE0; mesh nh&#x1EB1;m gi&#x1EA3;m Draw Call - T&#x1ED1;i &#x1B0;u game Unity" loading="lazy"></p>
<p>B&#x1B0;&#x1EDB;c 2: Ch&#x1ECD;n c&#xE1;c mesh c&#x1EA7;n g&#x1ED9;p</p>
<p>&#x110;&#x1EC3; ch&#x1ECD;n c&#xE1;c mesh Mesk Baker cung c&#x1EA5;p 2 l&#x1EF1;a ch&#x1ECD;n</p>
<p>i. List tr&#x1EF1;c ti&#x1EBF;p trong Sence</p>
<p>T&#x1EA1;i Object MaterialBaker, ch&#x1ECD;n Open Tools For Adding Objects.<br>
T&#x1EA1;i m&#x1EE5;c Analyse Sense &amp; Generate Bakers, Ch&#x1ECD;n Select Folder For Combined Material Assets &#x111;&#x1EC3; ch&#x1ECD;n folder l&#x1B0;u (folder Combined), r&#x1ED3;i ch&#x1ECD;n List Shaders In Scene.</p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/05/3.png" alt="Unity Tool - S&#x1EED; d&#x1EE5;ng Mesh Baker &#x111;&#x1EC3; h&#x1EE3;p nh&#x1EA5;t c&#xE1;c material v&#xE0; mesh nh&#x1EB1;m gi&#x1EA3;m Draw Call - T&#x1ED1;i &#x1B0;u game Unity" loading="lazy"></p>
<p>ii. Ch&#x1ECD;n th&#x1EE7; c&#xF4;ng t&#x1EEB;ng mesh c&#x1EA7;n g&#x1ED9;p</p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/05/4.png" alt="Unity Tool - S&#x1EED; d&#x1EE5;ng Mesh Baker &#x111;&#x1EC3; h&#x1EE3;p nh&#x1EA5;t c&#xE1;c material v&#xE0; mesh nh&#x1EB1;m gi&#x1EA3;m Draw Call - T&#x1ED1;i &#x1B0;u game Unity" loading="lazy"></p>
<p>B&#x1B0;&#x1EDB;c 3 : Bake</p>
<p>Sau khi ch&#x1ECD;n xong c&#xE1;c mesh c&#x1EA7;n g&#x1ED9;p ch&#xFA;ng ta ch&#x1ECD;n bake &#x111;&#x1EC3; g&#x1ED9;p c&#xE1;c mesh</p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/05/5.png" alt="Unity Tool - S&#x1EED; d&#x1EE5;ng Mesh Baker &#x111;&#x1EC3; h&#x1EE3;p nh&#x1EA5;t c&#xE1;c material v&#xE0; mesh nh&#x1EB1;m gi&#x1EA3;m Draw Call - T&#x1ED1;i &#x1B0;u game Unity" loading="lazy"></p>
<p>K&#x1EBF;t qu&#x1EA3; c&#x1EE7;a vi&#x1EC7;c bake</p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/05/6.png" alt="Unity Tool - S&#x1EED; d&#x1EE5;ng Mesh Baker &#x111;&#x1EC3; h&#x1EE3;p nh&#x1EA5;t c&#xE1;c material v&#xE0; mesh nh&#x1EB1;m gi&#x1EA3;m Draw Call - T&#x1ED1;i &#x1B0;u game Unity" loading="lazy"></p>
<h2 id="3mtsoptionkhc">3. M&#x1ED9;t s&#x1ED1; option kh&#xE1;c</h2>
<p>Vi&#x1EC7;c bake mesh c&#xF3; th&#x1EC3; l&#x1EF1;a ch&#x1ECD;n c&#xE1;c c&#xE1;ch out put kh&#xE1;c nhau</p>
<ul>
<li>Bake into Prefab</li>
<li>Bake into Scene Object</li>
<li>Bake Mesh Asset in place</li>
</ul>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/05/7.png" alt="Unity Tool - S&#x1EED; d&#x1EE5;ng Mesh Baker &#x111;&#x1EC3; h&#x1EE3;p nh&#x1EA5;t c&#xE1;c material v&#xE0; mesh nh&#x1EB1;m gi&#x1EA3;m Draw Call - T&#x1ED1;i &#x1B0;u game Unity" loading="lazy"></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Hướng dẫn sử dụng công cụ OWASP ZAP để quét lỗ hổng bảo mật ứng dụng web]]></title><description><![CDATA[<!--kg-card-begin: markdown--><h1 id="nidungtrnhby">N&#x1ED9;i dung tr&#xEC;nh b&#xE0;y:</h1>
<ol>
<li>OWASP ZAP l&#xE0; g&#xEC;</li>
<li>C&#xE0;i &#x111;&#x1EB7;t</li>
<li>S&#x1EED; d&#x1EE5;ng nh&#x1B0; th&#x1EBF; n&#xE0;o</li>
</ol>
<h1 id="owaspzaplg">OWASP ZAP l&#xE0; g&#xEC;</h1>
<ul>
<li>L&#xE0; c&#xF4;ng c&#x1EE5; qu&#xE9;t</li></ul>]]></description><link>https://blog.arrow-tech.vn/owasp-zap/</link><guid isPermaLink="false">63915acd7a2f410001205daf</guid><category><![CDATA[Security]]></category><category><![CDATA[Testing]]></category><dc:creator><![CDATA[dungbv]]></dc:creator><pubDate>Thu, 24 May 2018 07:10:12 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><h1 id="nidungtrnhby">N&#x1ED9;i dung tr&#xEC;nh b&#xE0;y:</h1>
<ol>
<li>OWASP ZAP l&#xE0; g&#xEC;</li>
<li>C&#xE0;i &#x111;&#x1EB7;t</li>
<li>S&#x1EED; d&#x1EE5;ng nh&#x1B0; th&#x1EBF; n&#xE0;o</li>
</ol>
<h1 id="owaspzaplg">OWASP ZAP l&#xE0; g&#xEC;</h1>
<ul>
<li>L&#xE0; c&#xF4;ng c&#x1EE5; qu&#xE9;t l&#x1ED7;i b&#x1EA3;o m&#x1EAD;t c&#x1EE7;a &#x1EE9;ng d&#x1EE5;ng web, m&#xE3; ngu&#x1ED3;n m&#x1EDF;.</li>
<li>C&#xE1;c t&#xED;nh n&#x103;ng c&#x1EE7;a ZAP:
<ul>
<li>Zap nh&#x1B0; m&#x1ED9;t proxy gi&#x1EEF;a tr&#xEC;nh duy&#x1EC7;t v&#xE0; web app, do &#x111;&#xF3; ta c&#xF3; th&#x1EC3; inspect, modify nh&#x1EEF;ng request &#x111;&#x1B0;&#x1EE3;c g&#x1EED;i &#x111;&#x1EBF;n app.<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/05/zap0.png" alt="zap0" loading="lazy"></li>
<li>Spider: l&#xE0; t&#xED;nh n&#x103;ng &#x111;&#x1B0;&#x1EE3;c s&#x1EED; d&#x1EE5;ng &#x111;&#x1EC3; t&#x1EF1; &#x111;&#x1ED9;ng kh&#xE1;m ph&#xE1; ra nh&#x1EEF;ng URL tr&#xEA;n website. N&#xF3; b&#x1EAF;t &#x111;&#x1EA7;u v&#x1EDB;i m&#x1ED9;t danh s&#xE1;ch URL, sau &#x111;&#xF3; x&#xE1;c &#x111;&#x1ECB;nh t&#x1EA5;t c&#x1EA3; c&#xE1;c URL c&#xF3; tr&#xEA;n c&#xE1;c trang v&#xE0; th&#xEA;m ch&#xFA;ng v&#xE0;o danh s&#xE1;ch URL c&#x1EA7;n th&#x103;m ti&#x1EBF;p theo, &#x111;&#x1EC7; quy ti&#x1EBF;p t&#x1EE5;c &#x111;&#x1EC3; t&#xEC;m &#x111;&#x1B0;&#x1EE3;c URL m&#x1EDB;i.</li>
<li>Active scan: l&#xE0; t&#xED;nh n&#x103;ng t&#x1EF1; &#x111;&#x1ED9;ng scan &#x111;&#x1EC3; t&#xEC;m nh&#x1EEF;ng l&#x1ED7;i &#x111;&#xE3; &#x111;&#x1B0;&#x1EE3;c bi&#x1EBF;t tr&#x1B0;&#x1EDB;c.</li>
<li>Passive scan: khi Zap &#x111;&#x1B0;&#x1EE3;c &#x111;&#x1EB7;t l&#xE0;m proxy cho tr&#xEC;nh duy&#x1EC7;t, n&#xF3; s&#x1EBD; scan t&#x1EA5;t c&#x1EA3; HTTP message (request v&#xE0; response) &#x111;&#x1B0;&#x1EE3;c g&#x1EED;i &#x111;&#x1EBF;n web app &#x111;&#x1EC3; x&#xE1;c &#x111;&#x1ECB;nh l&#x1ED7;i. Passive scan kh&#xF4;ng thay &#x111;&#x1ED5;i request v&#xE0; response.</li>
<li>Fuzzing: l&#xE0; t&#xED;nh n&#x103;ng cho ph&#xE9;p submit nhi&#x1EC1;u d&#x1EEF; li&#x1EC7;u kh&#xF4;ng h&#x1EE3;p l&#x1EC7; l&#xEA;n server.</li>
<li>....</li>
</ul>
</li>
</ul>
<h1 id="cit">C&#xE0;i &#x111;&#x1EB7;t</h1>
<ul>
<li>Download v&#xE0; c&#xE0;i &#x111;&#x1EB7;t theo h&#x1B0;&#x1EDB;ng d&#x1EAB;n t&#x1EA1;i &#x111;&#xE2;y:<br>
<a href="http://">https://github.com/zaproxy/zaproxy/wiki/Downloads<br>
</a></li>
</ul>
<h1 id="sdng">S&#x1EED; d&#x1EE5;ng</h1>
<h2 id="khito">Kh&#x1EDF;i t&#x1EA1;o</h2>
<ol>
<li>
<p>Explore app th&#x1EE7; c&#xF4;ng</p>
<ul>
<li>Sau khi start Zap, b&#x1B0;&#x1EDB;c &#x111;&#x1EA7;u ti&#xEA;n ta n&#xEA;n explore app th&#x1EE7; c&#xF4;ng, s&#x1EED; d&#x1EE5;ng t&#x1ED1;i &#x111;a c&#xE1;c ch&#x1EE9;c n&#x103;ng m&#xE0; web app cung c&#x1EA5;p, b&#x1EDF;i c&#xF3; nh&#x1EEF;ng t&#xED;nh n&#x103;ng c&#x1EA7;n d&#x1EEF; li&#x1EC7;u h&#x1EE3;p l&#x1EC7; &#x111;&#x1EC3; c&#xF3; th&#x1EC3; ti&#x1EBF;p t&#x1EE5;c.</li>
<li>&#x110;&#x1EC3; explore, ta Launch Browser &#x1EDF; tab Quick Start ho&#x1EB7;c &#x111;&#x1EB7;t Zap l&#xE0; proxy cho tr&#xEC;nh duy&#x1EC7;t (Preference --&gt; Local Proxy)</li>
</ul>
</li>
<li>
<p>Sau khi &#x111;&#xE3; explore, ta n&#xEA;n l&#x1B0;u session &#x111;&#x1EC3; t&#xE1;i s&#x1EED; d&#x1EE5;ng l&#x1EA7;n sau</p>
</li>
<li>
<p>T&#x1EA1;o Context</p>
<ul>
<li>Context l&#xE0; m&#x1ED9;t t&#x1EAD;p url, th&#x1B0;&#x1EDD;ng l&#xE0; m&#x1ED9;t web app</li>
<li>Context cung c&#x1EA5;p c&#xE1;c t&#xED;nh n&#x103;ng quan tr&#x1ECD;ng nh&#x1B0;: Authentication, Users, Session Management&#x2026;</li>
<li>N&#x1EBF;u web app cung c&#x1EA5;p nhi&#x1EC1;u role, ta n&#xEA;n l&#x1B0;u m&#x1ED7;i role v&#xE0;o m&#x1ED9;t Zap session.</li>
<li>C&#xE1;c b&#x1B0;&#x1EDB;c t&#x1EA1;o context:
<ul>
<li>Trong ph&#x1EA7;n Sites, click icon New Context, sau &#x111;&#xF3; t&#x1EA1;o context m&#x1EDB;i</li>
<li>Double click v&#xE0;o context v&#x1EEB;a t&#x1EA1;o<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/05/Screen-Shot-2018-05-24-at-10.05.42-AM.png" alt="Screen-Shot-2018-05-24-at-10.05.42-AM" loading="lazy"></li>
<li>M&#x1EE5;c Authencitation: ch&#x1ECD;n Authentication mehtod ph&#xF9; h&#x1EE3;p<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/05/Screen-Shot-2018-05-24-at-10.23.14-AM.png" alt="Screen-Shot-2018-05-24-at-10.23.14-AM" loading="lazy"></li>
<li>M&#x1EE5;c Users: click Add &#x111;&#x1EC3; th&#xEA;m m&#x1EDB;i m&#x1ED9;t user<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/05/Screen-Shot-2018-05-24-at-10.26.04-AM.png" alt="Screen-Shot-2018-05-24-at-10.26.04-AM" loading="lazy"></li>
</ul>
</li>
</ul>
</li>
<li>
<p>Include web app v&#xE0;o context v&#x1EEB;a t&#x1EA1;o<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/05/Screen-Shot-2018-05-24-at-10.37.55-AM.png" alt="Screen-Shot-2018-05-24-at-10.37.55-AM" loading="lazy"></p>
</li>
<li>
<p>Th&#xEA;m nh&#x1EEF;ng context c&#x1EA7;n quan t&#xE2;m v&#xE0; lo&#x1EA1;i nh&#x1EEF;ng context kh&#xE1;c t&#x1EEB; Scope b&#x1EB1;ng c&#xE1;ch chu&#x1ED9;t ph&#x1EA3;i v&#xE0;o m&#x1ED7;i context, sau &#x111;&#xF3; click icon Show only URL in Scope<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/05/Screen-Shot-2018-05-24-at-10.43.28-AM.png" alt="Screen-Shot-2018-05-24-at-10.43.28-AM" loading="lazy"></p>
</li>
</ol>
<h2 id="tnhnngspidervactivescan">T&#xED;nh n&#x103;ng Spider v&#xE0; Active Scan</h2>
<ol>
<li>
<p>Ch&#x1ECD;n Attack --&gt; Spider<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/05/Screen-Shot-2018-05-24-at-10.55.21-AM.png" alt="Screen-Shot-2018-05-24-at-10.55.21-AM" loading="lazy"></p>
</li>
<li>
<p>Ch&#x1ECD;n Context, User, sau &#x111;&#xF3; Start Scan<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/05/Screen-Shot-2018-05-24-at-10.56.53-AM.png" alt="Screen-Shot-2018-05-24-at-10.56.53-AM" loading="lazy"></p>
</li>
<li>
<p>Active Scan c&#x169;ng t&#x1B0;&#x1A1;ng t&#x1EF1;, k&#x1EBF;t qu&#x1EA3; s&#x1EBD; &#x111;&#x1B0;&#x1EE3;c show trong tab Alert</p>
</li>
</ol>
<h2 id="tnhnngfuzzing">T&#xED;nh n&#x103;ng Fuzzing</h2>
<ol>
<li>Ch&#x1ECD;n m&#x1ED9;t submit request t&#x1EEB; ph&#x1EA7;n Sites c&#x1EA7;n test, sau &#x111;&#xF3; ch&#x1ECD;n Fuzz t&#x1EEB; menu Attack</li>
<li>Double click m&#x1ED9;t tham s&#x1ED1; c&#x1EA7;n g&#xE1;n nhi&#x1EC1;u gi&#xE1; tr&#x1ECB;, t&#x1EA1;i m&#x1EE5;c Fuzz Locations --&gt; Add --&gt; Add --&gt; Ch&#x1ECD;n payload type c&#x1EA7;n test --&gt; Add --&gt; Start Fuzzer<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/05/Screen-Shot-2018-05-24-at-11.10.05-AM.png" alt="Screen-Shot-2018-05-24-at-11.10.05-AM" loading="lazy"></li>
</ol>
<h1 id="more">More</h1>
<p>&#x110;&#x1EC3; t&#xEC;m hi&#x1EC3;u chi ti&#x1EBF;t, ch&#x1ECD;n Help --&gt; OWASP ZAP User Guide</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Quản lý log với mô hình ELK]]></title><description><![CDATA[<!--kg-card-begin: markdown--><h1 id="elkstacklg">ELK stack l&#xE0; g&#xEC;</h1>
<p><em>&quot;ELK&quot; l&#xE0; vi&#x1EBF;t t&#x1EAF;t c&#x1EE7;a 3 m&#xE3; ngu&#x1ED3;n m&#x1EDF;: Elasticsearch, Logstash, and Kibana</em></p>
<p><strong>Elasticsearch</strong>: C&#x1A1; s&#x1EDF; d&#x1EEF; li&#x1EC7;u &#x111;&#x1EC3; l&#x1B0;u tr&#x1EEF;, t&</p>]]></description><link>https://blog.arrow-tech.vn/quan-ly-log-voi-mo-hinh-elk/</link><guid isPermaLink="false">63915acd7a2f410001205dad</guid><dc:creator><![CDATA[honglm]]></dc:creator><pubDate>Thu, 17 May 2018 09:11:41 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><h1 id="elkstacklg">ELK stack l&#xE0; g&#xEC;</h1>
<p><em>&quot;ELK&quot; l&#xE0; vi&#x1EBF;t t&#x1EAF;t c&#x1EE7;a 3 m&#xE3; ngu&#x1ED3;n m&#x1EDF;: Elasticsearch, Logstash, and Kibana</em></p>
<p><strong>Elasticsearch</strong>: C&#x1A1; s&#x1EDF; d&#x1EEF; li&#x1EC7;u &#x111;&#x1EC3; l&#x1B0;u tr&#x1EEF;, t&#xEC;m ki&#x1EBF;m v&#xE0; query log<br>
<strong>Logstash</strong>: Ti&#x1EBF;p nh&#x1EAD;n log t&#x1EEB; nhi&#x1EC1;u ngu&#x1ED3;n, sau &#x111;&#xF3; x&#x1EED; l&#xFD; log v&#xE0; ghi d&#x1EEF; li&#x1EC7;u v&#xE0; Elasticsearch<br>
<strong>Kibana</strong>: Giao di&#x1EC7;n &#x111;&#x1EC3; qu&#x1EA3;n l&#xFD;, th&#x1ED1;ng k&#xEA; log. &#x110;&#x1ECD;c th&#xF4;ng tin t&#x1EEB; Elasticsearch</p>
<p>V&#x1EC1; c&#x1A1; ch&#x1EBF; ho&#x1EA1;t &#x111;&#x1ED9;ng b&#x1EA1;n c&#xF3; th&#x1EC3; xem h&#xEC;nh b&#xEA;n d&#x1B0;&#x1EDB;i<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/05/elk1.jpeg" alt="elk1" loading="lazy"></p>
<ul>
<li>&#x110;&#x1EA7;u ti&#xEA;n th&#xEC; log s&#x1EBD; &#x111;&#x1B0;&#x1EE3;c &#x111;&#x1B0;a &#x111;&#x1EBF;n Logstash qua nhi&#x1EC1;u con &#x111;&#x1B0;&#x1EDD;ng, t&#x1EEB; file, t&#x1EEB; beat (C&#xF4;ng c&#x1EE5; &#x111;&#x1ECD;c file c&#x1EE7;a elastic.co)</li>
<li>Sau &#x111;&#xF3; Logstash s&#x1EBD; x&#x1EED; l&#xFD;, v&#xE0; ph&#xE2;n lo&#x1EA1;i log r&#x1ED3;i &#x111;&#x1B0;a &#x111;&#x1EBF;n Elastic Search &#x111;&#x1EC3; l&#x1B0;u tr&#x1EEF;</li>
<li>Kibana s&#x1EBD; &#x111;&#x1ECD;c nh&#x1EEF;ng d&#x1EEF; li&#x1EC7;u &#x111;&#x1B0;&#x1EE3;c l&#x1B0;u trong Elastic Search &#x111;&#x1EC3; hi&#x1EC7;n th&#x1ECB; log</li>
</ul>
<h1 id="buildelkstackvidocker">Build ELK stack v&#x1EDB;i docker</h1>
<ul>
<li>&#x110;&#x1EA7;u ti&#xEA;n pull 3 image elk v&#x1EC1; m&#xE1;y:<pre><code>docker pull docker.elastic.co/elasticsearch/elasticsearch:6.2.4
docker pull docker.elastic.co/kibana/kibana:6.2.4
docker pull docker.elastic.co/logstash/logstash:6.2.4
</code></pre>
</li>
<li>T&#x1EA1;o folder c&#xF3; c&#x1EA5;u tr&#xFA;c sau:<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/05/docker_elk.png" alt="docker_elk" loading="lazy"></li>
</ul>
<p>docker-compose.yml</p>
<pre><code>version: &apos;2&apos;
services:
 elasticsearch:
 	container_name: elastic_624
   image: docker.elastic.co/elasticsearch/elasticsearch:6.2.4
   build: elasticsearch
   environment:
     ES_JAVA_OPTS: &quot;-Xms1g -Xmx1g&quot;
   ports:
     - &quot;9203:9200&quot;
     - &quot;9302:9300&quot;
   volumes:
     - ./elasticsearch/config/:/etc/elasticsearch/config/
 kibana:
   container_name: kibana_624
   image: docker.elastic.co/kibana/kibana:6.2.4
   build: kibana
   ports:
     - 5601:5601
   volumes:
     - ./kibana/config/:/opt/kibana/config/
   depends_on:
     - elasticsearch
 logstash:
 	container_name: logstash_624
 	image: docker.elastic.co/logstash/logstash:6.2.4
 	command: -f /etc/logstash/conf.d/
   build:logstash
   ports:
     - 5000:5000
   volumes:
     - ./logstash/config:/etc/logstash/conf.d
   depends_on:
     - elasticsearch
</code></pre>
<p>kibana.yml</p>
<pre><code>server.name: &quot;kibana&quot;
server.host: &quot;0.0.0.0&quot;
ops.interval: 5000
elasticsearch.url: &quot;[ip_server_here]:9203&quot;
xpack.security.enabled: false
</code></pre>
<p>my_config.conf</p>
<pre><code>input {
    file {
    	path =&gt; &quot;your file log&quot;
        type =&gt; &quot;Name of Log&quot;
    }
}
output {
    elasticsearch { 
    	hosts =&gt; [&quot;localhost:9200&quot;] 
    }
    if &quot;INFO&quot; in [message] {
	    email {
	        username =&gt; &quot;yourmail@gmail.com&quot;
	        address =&gt; &quot;smtp.gmail.com&quot;
	        password =&gt; &quot;yourpass&quot;
	        port =&gt; 587
	        use_tls =&gt; true
	        from =&gt; &quot;yourmail@gmail.com&quot;
	        subject =&gt; &quot;LOG alert&quot;
	        to =&gt; &quot;yourmail@gmail.com&quot;
	        via =&gt; &quot;smtp&quot;
	        body =&gt; &quot;Here is the event line that occured: %{message}&quot;
	    }
    }
    stdout { codec =&gt; rubydebug }
}
</code></pre>
<ul>
<li>Run:
<ul>
<li>Trong folder ch&#x1EE9;a file docker-compose.yml ch&#x1EA1;y l&#x1EC7;nh <code>docker-compose up</code></li>
<li>Ch&#x1EA1;y th&#xE0;nh c&#xF4;ng s&#x1EBD; c&#xF3; 3 container nh&#x1B0; h&#xEC;nh b&#xEA;n d&#x1B0;&#x1EDB;i<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/05/docker_elk_running.png" alt="docker_elk_running" loading="lazy"></li>
<li>&#x110;&#x1ECB;a ch&#x1EC9; truy c&#x1EAD;p v&#xE0;o kibana: your_ip:5601</li>
</ul>
</li>
</ul>
<!--kg-card-end: markdown-->]]></content:encoded></item></channel></rss>