<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Mobilesprogramming&#039;s Blog</title>
	<atom:link href="http://mobilesprogramming.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://mobilesprogramming.wordpress.com</link>
	<description>JAVA &#124; SYMBIAN &#124; ANDROID</description>
	<lastBuildDate>Thu, 05 May 2011 10:47:16 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='mobilesprogramming.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Mobilesprogramming&#039;s Blog</title>
		<link>http://mobilesprogramming.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://mobilesprogramming.wordpress.com/osd.xml" title="Mobilesprogramming&#039;s Blog" />
	<atom:link rel='hub' href='http://mobilesprogramming.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Cơ Bản Android &#8211; ViewGroup Và Custom Adapter &#8211; P4</title>
		<link>http://mobilesprogramming.wordpress.com/2011/03/30/c%c6%a1-b%e1%ba%a3n-android-viewgroup-va-custom-adapter-p4/</link>
		<comments>http://mobilesprogramming.wordpress.com/2011/03/30/c%c6%a1-b%e1%ba%a3n-android-viewgroup-va-custom-adapter-p4/#comments</comments>
		<pubDate>Wed, 30 Mar 2011 10:11:28 +0000</pubDate>
		<dc:creator>mobilesprogramming</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Android Tutorial]]></category>
		<category><![CDATA[android_basic]]></category>
		<category><![CDATA[android_tutorial]]></category>

		<guid isPermaLink="false">http://mobilesprogramming.wordpress.com/?p=802</guid>
		<description><![CDATA[I.Custom ViewGroup ViewGroup thông thường chúng ta hay gặp là LinearLayout, Relative Layout. Xây dựng custom ViewGroup cho phép chúng ta tạo 1 tập các widget được sắp xếp theo ý muốn rồi đưa vào sử dụng. Yêu cầu: Xây dựng ứng dụng dạng To Do List: Cho phép nhập vào nội dung công việc [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mobilesprogramming.wordpress.com&amp;blog=11410337&amp;post=802&amp;subd=mobilesprogramming&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<h2>I.Custom ViewGroup</h2>
<p>ViewGroup thông thường chúng ta hay gặp là LinearLayout, Relative Layout. Xây dựng custom ViewGroup cho phép chúng ta tạo 1 tập các widget được sắp xếp theo ý muốn rồi đưa vào sử dụng.</p>
<p>Yêu cầu: Xây dựng ứng dụng dạng To Do List: Cho phép nhập vào nội dung công việc và thời gian thực hiện công việc rồi đưa vào list công việc. Cho phép xóa các công việc khỏi list.</p>
<p><strong><em><span style="text-decoration:underline;">B1:</span></em></strong> Khởi tạo project: File -&gt; New -&gt; Android Project<br />
Project name: Example 3<br />
Build Target: Chọn Android 1.5<br />
Application name: Example 3<br />
Package name: at.exam<br />
Create Activity: Example<br />
=&gt; Kích nút Finish.</p>
<p><strong><em><span style="text-decoration:underline;">B2:</span></em></strong> Xây dựng custom view group trong XML. Đi tới res\layout tạo 1 file XML mới là list.xml. Gõ nội dung sau vào:<span id="more-802"></span></p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="590" valign="top">
<pre>&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:orientation="horizontal"&gt;
    &lt;CheckBox
          android:id="@+id/check_work"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text=""
          android:paddingTop="45px"
          android:paddingRight="10px"         
      /&gt;
      &lt;LinearLayout
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:orientation="vertical"         
      &gt;
          &lt;TextView
              android:id="@+id/work_content"
              android:textSize="24px"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:lines="1"
              android:textColor="@color/work_color"
          /&gt;
          &lt;TextView
              android:id="@+id/time_content"
              android:textSize="16px"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:lines="1"
              android:textColor="@color/time_color"
          /&gt;
      &lt;/LinearLayout&gt;
&lt;/LinearLayout&gt;</pre>
</td>
</tr>
</tbody>
</table>
<p>Custom ViewGroup của chúng ta ở đây khá đơn giản, đó là 1 LinearLayout chứa 2 thành phần: 1 CheckBox và 1 LinearLayout khác gồm 2 TextView để hiển thị nội dung công việc và thời gian.</p>
<p><strong><em><span style="text-decoration:underline;">B3:</span></em></strong> Đã xong giao diện cho custom ViewGroup, chúng ta sẽ thiết kế giao diện cho chương trình trong main.xml. Ở đây mình dùng lại giao diện của Example 2 trong bài 2.</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="590" valign="top">
<pre>&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    &gt;
    &lt;EditText
        android:id="@+id/work_enter"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:hint="@string/work_hint"
        android:lines="1"
        android:textSize="24px"
    /&gt;
    &lt;LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        &gt;
        &lt;TextView
            android:layout_width="50px"
            android:layout_height="wrap_content"
            android:text="@string/hour_edit"
            android:typeface="normal"
            android:textSize="15px"
            android:textStyle="bold"
            android:padding="5px"
        /&gt;
        &lt;EditText
            android:id="@+id/hour_edit"
            android:layout_width="45px"
            android:layout_height="wrap_content"
            android:hint="12"
            android:textColorHint="@color/hint_color"
            android:textSize="20px"
            android:gravity="center"
            android:padding="5px"
            android:numeric="integer"
            android:maxLength="2"
        /&gt;
        &lt;TextView
            android:layout_width="65px"
            android:layout_height="wrap_content"
            android:text="@string/minute_edit"
            android:typeface="normal"
            android:textSize="15px"
            android:textStyle="bold"
            android:padding="5px"
        /&gt;
        &lt;EditText
            android:id="@+id/minute_edit"
            android:layout_width="45px"
            android:layout_height="wrap_content"
            android:hint="00"
            android:textColorHint="@color/hint_color"
            android:textSize="20px"
            android:gravity="center"
            android:padding="5px"
            android:numeric="integer"
            android:maxLength="2"
        /&gt;       
    &lt;/LinearLayout&gt;
    &lt;Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="@string/button_content"
        /&gt;
    &lt;ListView
        android:id="@+id/list"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
    /&gt;
&lt;/LinearLayout&gt;</pre>
</td>
</tr>
</tbody>
</table>
<p><strong><em><span style="text-decoration:underline;">B4:</span></em></strong> Tạo file colors.xml trong res\value:</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="590" valign="top">
<pre>&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;resources&gt;
    &lt;color name="work_color"&gt;#ffffff&lt;/color&gt;
    &lt;color name="time_color"&gt;#cccccc&lt;/color&gt;   
    &lt;color name="hint_color"&gt;#cccccc&lt;/color&gt;
&lt;/resources&gt;</pre>
</td>
</tr>
</tbody>
</table>
<p>work_color là màu của nội dung công việc trong list. time_color màu của thời gian công việc. hint_color màu của text hint (dòng hướng dẫn) các EditText.</p>
<p><strong><em><span style="text-decoration:underline;">B5:</span></em></strong> Chỉnh sửa file strings.xml trong res\value:</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="590" valign="top">
<pre>&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;resources&gt;
    &lt;string name="app_name"&gt;Example 3&lt;/string&gt;
    &lt;string name="work_hint"&gt;Enter the work here&lt;/string&gt;
    &lt;string name="hour_edit"&gt;Hour&lt;/string&gt;
    &lt;string name="minute_edit"&gt;Minute&lt;/string&gt;
    &lt;string name="button_content"&gt;Add work&lt;/string&gt;
&lt;/resources&gt;</pre>
</td>
</tr>
</tbody>
</table>
<p><strong><em><span style="text-decoration:underline;">B6:</span></em></strong> Time to coding. Đi tới src\at.exam tạo một class mới là CustomViewGroup với nội dung sau:</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="590" valign="top">
<pre>package at.exam;

import android.content.Context;
import android.view.LayoutInflater;
import android.widget.CheckBox;
import android.widget.LinearLayout;
import android.widget.TextView;

public class CustomViewGroup extends LinearLayout {
    public CheckBox cb;
    public TextView workContent;
    public TextView timeContent;
    public CustomViewGroup(Context context) {
        super(context);

        //Sử dụng LayoutInflater để gán giao diện trong list.xml cho class này
        LayoutInflater li = (LayoutInflater) this.getContext()
                                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        li.inflate(R.layout.list, this, true);

        //Lấy về các View qua Id
        cb = (CheckBox) findViewById(R.id.check_work);
        workContent = (TextView) findViewById(R.id.work_content);
        timeContent = (TextView) findViewById(R.id.time_content);
    }
}</pre>
</td>
</tr>
</tbody>
</table>
<p>Đoạn code trên giúp ta định nghĩa giao diện của custom ViewGroup mới dựa trên file list.xml. Mọi người cũng có thể tạo giao diện bằng code, ko cần sử dụng XML nhưng sẽ phức tạp hơn và mình cũng ko giới thiệu ở đây.</p>
<p><strong><em><span style="text-decoration:underline;">B7:</span></em></strong> Tạo 1 class Work cũng trong at.exam để thể hiện công việc:</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="590" valign="top">
<pre>package at.exam;

public class Work {
    private String workContent;
    private String timeContent;
    private boolean isChecked;

    public Work(String workContent, String timeContent) {
        this.workContent = workContent;
        this.timeContent = timeContent;
        isChecked = false;
    }

    public String getContent() {
        return workContent;
    }

    public String getTime() {
        return timeContent;
    }

    public void setChecked(boolean isChecked) {
        this.isChecked = isChecked;
    }

    public boolean isChecked() {
        return isChecked;
    }
}</pre>
</td>
</tr>
</tbody>
</table>
<p>Code rất đơn giản nên mình sẽ không chú thích nữa.</p>
<p><strong><em><span style="text-decoration:underline;">B8:</span></em></strong> Chúng ta đã tạo xong custem ViewGroup, bây giờ chính là lúc sử dụng. Tạo 1 class mới tên là ListWorkApdapter trong at.exam:</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="590" valign="top">
<pre>package at.exam;

import java.util.ArrayList;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.TextView;
import android.widget.CompoundButton.OnCheckedChangeListener;

public class ListWorkAdapter extends ArrayAdapter&lt;Work&gt;{
    ArrayList&lt;Work&gt; array;
    int resource;
    Context context;

    public ListWorkAdapter(Context context, int textViewResourceId,
            ArrayList&lt;Work&gt; objects) {
        super(context, textViewResourceId, objects);
        this.context = context;
        resource = textViewResourceId;
        array = objects;       
    }    

    //Phương thức xác định View mà Adapter hiển thị, ở đây chính là CustomViewGroup
    //Bắt buộc phải Override khi kế thừa từ ArrayAdapter
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View workView = convertView;

        if (workView == null) {
            workView = new CustomViewGroup(getContext());
        }

        //Lấy về đối tượng Work hiện tại
        final Work work = array.get(position);

        if (work != null) {
            TextView workContent = ((CustomViewGroup) workView).workContent;
            TextView timeContent = ((CustomViewGroup) workView).timeContent;
            CheckBox checkWork = ((CustomViewGroup) workView).cb;

            //Set sự kiện khi đánh dấu vào checkbox trên list
            checkWork.setOnCheckedChangeListener(new OnCheckedChangeListener() {

                @Override
                public void onCheckedChanged(CompoundButton buttonView,
                        boolean isChecked) {
                    work.setChecked(isChecked);                   
                }               
            });

            //Lấy về nội dung cho TextView và CheckBox dựa vào đối tượng Work hiện tại
            workContent.setText(work.getContent());
            timeContent.setText(work.getTime());
            checkWork.setChecked(work.isChecked());
        }       
        return workView;
    }   
}</pre>
</td>
</tr>
</tbody>
</table>
<p>ListWorkAdapter sẽ được sử dụng thay thế cho ArrayAdapter được bind với ListView. Thông thường ArrayAdapter chỉ cho hiển thị String bằng TextView, nhưng với việc kế thừa và override phương thức getView, ta có thể định nghĩa lại hiển thị cho các thành phần của ListView.</p>
<p><strong><em><span style="text-decoration:underline;">B9:</span></em></strong> Việc cuối cùng cần làm là viết lại Activity. Tới Example.java và chỉnh sửa theo nội dung sau:</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="590" valign="top">
<pre>package at.exam;

import java.util.ArrayList;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;

public class Example extends Activity {   
    //Các hằng dùng cho tạo Option Menu
    private static final int DELETE_WORK = Menu.FIRST;
    private static final int ABOUT = Menu.FIRST + 2;

    ArrayList&lt;Work&gt; array;
    ListWorkAdapter arrayAdapter;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        array = new ArrayList&lt;Work&gt;();
        arrayAdapter = new ListWorkAdapter(this,
                R.layout.list, array);

        final EditText workEnter = (EditText) findViewById(R.id.work_enter);
        final EditText hourEdit = (EditText) findViewById(R.id.hour_edit);
        final EditText minuteEdit = (EditText) findViewById(R.id.minute_edit);

        final Button button = (Button) findViewById(R.id.button);

        //Tạo list view cho danh sách công việc
        final ListView list = (ListView) findViewById(R.id.list);
        list.setAdapter(arrayAdapter);

        OnClickListener add = new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (workEnter.getText().toString().equals("") ||
                        hourEdit.getText().toString().equals("") ||
                        minuteEdit.getText().toString().equals("")) {
                    AlertDialog.Builder builder = new AlertDialog.Builder(Example.this);
                    builder.setTitle("Info missing");
                    builder.setMessage("Please enter all information of the work");
                    builder.setPositiveButton("Continue", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            // TODO Auto-generated method stub                           
                        }                       
                    });
                    builder.show();
                }
                else {
                    String workContent = workEnter.getText().toString();
                    String timeContent = hourEdit.getText().toString() + ":"
                                    + minuteEdit.getText().toString();
                    Work work = new Work(workContent, timeContent);
                    array.add(0, work);
                    arrayAdapter.notifyDataSetChanged();
                    workEnter.setText("");
                    hourEdit.setText("");
                    minuteEdit.setText("");
                }
            }

        };

        button.setOnClickListener(add);       
    }

    //Tạo Option Menu
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);       
        menu.add(0, DELETE_WORK, 0,"Delete" ).setIcon(android.R.drawable.ic_delete);       
        menu.add(0, ABOUT, 0,"About" ).setIcon(android.R.drawable.ic_menu_info_details);
        return true;
    }

    //Xử lý sự kiện khi các option trong Option Menu được lựa chọn
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {           
            case DELETE_WORK: {
                deleteCheckedWork();
                break;
            }           
            case ABOUT: {
                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setTitle("VietAndroid");
                builder.setMessage("AUTHOR:" + "\n" + "  Nguyen Anh Tuan" + "\n" + "SOURCE:" + "\n" + "  diendan.vietandroid.com");
                builder.setPositiveButton("Close", new DialogInterface.OnClickListener() {                                    
                    public void onClick(DialogInterface dialog, int which) {
                    }
                });
                builder.setIcon(android.R.drawable.ic_dialog_info);
                builder.show();
                break;
            }
        }
        return true;
       }

    private void deleteCheckedWork() {
        if (array.size() &gt; 0) {
            for (int i = array.size() - 1; i &gt;= 0; i--) {
                if (array.get(i).isChecked()) {
                    array.remove(i);
                    arrayAdapter.notifyDataSetChanged();
                    continue;
                }
            }
        }       
    }
}</pre>
</td>
</tr>
</tbody>
</table>
<p>OK. Vậy là xong. Option Menu là menu ẩn chỉ hiện ra khi bạn nhấn nút Menu của điện thoại. Option Menu rất tiện trong việc đưa ra các tùy chỉnh, giống như khi bạn nhấn phím Esc khi đang chơi game trên PC vậy.</p>
<p>Các bạn có thể lưu ý là thay vì sử dụng ArrayList&lt;String&gt; như trước mình đã thay bằng ArrayList&lt;Work&gt; và trong khởi tạo đối tượng arrayAdapter thì đối số thứ 2 là R.layout.list thay vì android.R.layout.simple_list_item_1, nghĩa là chúng ta đã sử dụng layout do mình tự tạo thay vì layout Android cung cấp sẵn cho hiển thị các thành phần của ListView.</p>
<p>Nếu chạy thử, các bạn có thể thấy khi ta đánh dấu vào checkbox của 1 thành phần trong list, rồi nhấn Menu và chọn delete thì thành phần sẽ bị gỡ bỏ khỏi danh sách.</p>
<p>Tham khảo: http://vietandroid.com/tin-tuc.html.</p>
<p>Các bài viết liên quan:</p>
<p><a href="http://mobilesprogramming.wordpress.com/2011/03/24/c%C6%A1-b%E1%BA%A3n-android-%E2%80%93h%C6%B0%E1%BB%9Bng-d%E1%BA%ABn-l%E1%BA%ADp-trinh-c%C6%A1-b%E1%BA%A3n-v%E1%BB%9Bi-android-p3/">Cơ bản Android-Xây Dựng Giao Diện Cơ Bản &#8211; P3</a></p>
<div id="_mcePaste" class="mcePaste" style="position:absolute;left:-10000px;top:12607px;width:1px;height:1px;overflow:hidden;">
<h2 class="post-title">Cơ Bản Android – Xây Dựng Giao Diện Đơn Giản – P3</h2>
</div>
<br />Filed under: <a href='http://mobilesprogramming.wordpress.com/category/android/'>Android</a>, <a href='http://mobilesprogramming.wordpress.com/category/android/android-tutorial/'>Android Tutorial</a> Tagged: <a href='http://mobilesprogramming.wordpress.com/tag/android_basic/'>android_basic</a>, <a href='http://mobilesprogramming.wordpress.com/tag/android_tutorial/'>android_tutorial</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mobilesprogramming.wordpress.com/802/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mobilesprogramming.wordpress.com/802/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mobilesprogramming.wordpress.com/802/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mobilesprogramming.wordpress.com/802/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/mobilesprogramming.wordpress.com/802/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/mobilesprogramming.wordpress.com/802/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/mobilesprogramming.wordpress.com/802/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/mobilesprogramming.wordpress.com/802/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mobilesprogramming.wordpress.com/802/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mobilesprogramming.wordpress.com/802/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mobilesprogramming.wordpress.com/802/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mobilesprogramming.wordpress.com/802/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mobilesprogramming.wordpress.com/802/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mobilesprogramming.wordpress.com/802/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mobilesprogramming.wordpress.com&amp;blog=11410337&amp;post=802&amp;subd=mobilesprogramming&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mobilesprogramming.wordpress.com/2011/03/30/c%c6%a1-b%e1%ba%a3n-android-viewgroup-va-custom-adapter-p4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/992f5fba26e8af9ebb4a25d922f208c6?s=96&#38;d=&#38;r=G" medium="image">
			<media:title type="html">mobilesprogramming</media:title>
		</media:content>
	</item>
		<item>
		<title>Cơ Bản Android – Xây Dựng Giao Diện Đơn Giản &#8211; P3</title>
		<link>http://mobilesprogramming.wordpress.com/2011/03/24/c%c6%a1-b%e1%ba%a3n-android-%e2%80%93h%c6%b0%e1%bb%9bng-d%e1%ba%abn-l%e1%ba%adp-trinh-c%c6%a1-b%e1%ba%a3n-v%e1%bb%9bi-android-p3/</link>
		<comments>http://mobilesprogramming.wordpress.com/2011/03/24/c%c6%a1-b%e1%ba%a3n-android-%e2%80%93h%c6%b0%e1%bb%9bng-d%e1%ba%abn-l%e1%ba%adp-trinh-c%c6%a1-b%e1%ba%a3n-v%e1%bb%9bi-android-p3/#comments</comments>
		<pubDate>Thu, 24 Mar 2011 07:07:38 +0000</pubDate>
		<dc:creator>mobilesprogramming</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Android Tutorial]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[android_basic]]></category>
		<category><![CDATA[android_tutorial]]></category>

		<guid isPermaLink="false">http://mobilesprogramming.wordpress.com/?p=796</guid>
		<description><![CDATA[I.Android Manifest Trong khung Package Explorer, ở phía dưới thư mục res, bạn sẽ thấy 1 file có tên là AndroidManifest.xml. Mỗi ứng dụng đều cần có AndroidManifest.xml để mô tả những thông tin quan trọng của nó cho hệ thống Android biết. Let&#8217;s look closer: &#60;?xml version="1.0" encoding="utf-8"?&#62; &#60;manifest xmlns:android="http://schemas.android.com/apk/res/android"       package="at.exam"       android:versionCode="1" [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mobilesprogramming.wordpress.com&amp;blog=11410337&amp;post=796&amp;subd=mobilesprogramming&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<h2>I.Android Manifest</h2>
<p>Trong khung Package Explorer, ở phía dưới thư mục res, bạn sẽ thấy 1 file có tên là AndroidManifest.xml. Mỗi ứng dụng đều cần có AndroidManifest.xml để mô tả những thông tin quan trọng của nó cho hệ thống Android biết. Let&#8217;s look closer:</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="590" valign="top">
<pre>&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="at.exam"
      android:versionCode="1"
      android:versionName="1.0"&gt;
    &lt;application android:icon="@drawable/icon" android:label="@string/app_name"&gt;
        &lt;activity android:name=".Example"
                  android:label="@string/app_name"&gt;
            &lt;intent-filter&gt;
                &lt;action android:name="android.intent.action.MAIN" /&gt;
                &lt;category android:name="android.intent.category.LAUNCHER" /&gt;
            &lt;/intent-filter&gt;
        &lt;/activity&gt;
    &lt;/application&gt;
    &lt;uses-sdk android:minSdkVersion="3" /&gt;
&lt;/manifest&gt;</pre>
</td>
</tr>
</tbody>
</table>
<p>Cụ thể những công việc mà AndroidManifest.xml thực hiện:<br />
- Đặt tên cho Java package của ứng dụng.<br />
- Mô tả các thành phần (component) của ứng dụng: activity, service, broadcast receiver hoặc content provider.<br />
- Thông báo những permission mà ứng dụng cần có để truy nhập các protected API và tương tác với các ứng dụng khác.<br />
- Thông báo những permission mà các ứng dụng khác cần có để tương tác với ứng dụng hiện thời.<br />
- Thông báo level thấp nhất của Android API mà ứng dụng cần để chạy. (Android 1.0 là level 1, 1.1 là level 2, 1.5 level 3, 1.6 level 4 và 2.0 là level 5).<span id="more-796"></span><br />
&#8230;<br />
Hãy xem thử file AndroidManifest.xml của chương trình TooDo mình đang xây dựng:</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="590" valign="top">
<pre>&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="android.at"
      android:versionCode="1"
      android:versionName="1.0"&gt;
    &lt;application android:icon="@drawable/icon" android:label="@string/app_name"&gt;
        &lt;activity
                android:name=".TooDo"
                android:screenOrientation="landscape"
                android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
                android:label="@string/app_name"&gt;
            &lt;intent-filter&gt;
                &lt;action android:name="android.intent.action.MAIN" /&gt;
                &lt;category android:name="android.intent.category.LAUNCHER" /&gt;
            &lt;/intent-filter&gt;
        &lt;/activity&gt;
        &lt;activity android:name=".WorkEnter"&gt;
        &lt;/activity&gt;
        &lt;receiver android:name=".AlarmReceiver"&gt;
        &lt;/receiver&gt;
    &lt;/application&gt;
    &lt;uses-sdk android:minSdkVersion="3" /&gt;
    &lt;uses-permission android:name="android.permission.VIBRATE"/&gt;
&lt;/manifest&gt;</pre>
</td>
</tr>
</tbody>
</table>
<p>Main Activity của chương trình Too Do này là activity TooDo. Ngoài ra mình còn có 1 Activity khác có tên là WorkEnter để cho phép nhập vào thời gian và nội dung công việc. 1 Broadcast Receiver có tên là AlarmReceiver để nhận alarm gửi tới trong intent. Khi alarm được nhận sẽ có âm thanh và rung (vibration). Tất cả công việc sẽ được viết trong code, nhưng bắt buộc bạn phải khai báo các thành phần có trong ứng dụng vào AndroidManifest nếu muốn chương trình hoạt động. Tương tự, set permission để truy nhập camera, internet, đọc contact&#8230; cũng đều phải khai báo trong AM. Từ khóa screenOrientation cho phép thiết lập giao diện khi vào ứng dụng theo chiều dọc (portrait &#8211; mặc định) hay ngang (landscape), theme cho phép sử dụng style có sẵn của android là full-screen (ko có thanh status bar nữa).<br />
Intent filter là bộ lọc dùng để giới hạn các intent được sử dụng trong activity hay receiver&#8230;</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="590" valign="top">
<pre>&lt;intent-filter&gt;
        &lt;action android:name="android.intent.action.VIEW"/&gt;
        &lt;category android:name="android.intent.category.DEFAULT"/&gt;
        &lt;category android:name="android.intent.category.BROWSABLE"/&gt;
        &lt;data android:scheme="http" android:host="www.google.com" android:path="/m/products/scan"/&gt;
      &lt;/intent-filter&gt;</pre>
</td>
</tr>
</tbody>
</table>
<p>Bộ lọc trên chỉ cho phép intent mở internet với đường dẫn định nghĩa sẵn (<a href="http://www.google.com/m/products/scan" target="_blank">http://www.google.com/m/products/scan</a>). Ok, hi vọng mọi người đã nắm được chức năng cơ bản cũng như cách sử dụng Android Manifest.</p>
<h2>II.Working with View</h2>
<p>Trong bài 1 mình đã giới thiệu qua cách sử dụng Edit Text và Text View. Thực chất các View còn lại cũng có cách sử dụng tương tự, bạn sẽ kết hợp nhiều View khác nhau để cho ra giao diện mình mong muốn. Ở đây mình sẽ đề cập nhiều tới List View (theo ý kiến mình là View khó sử dụng nhất).</p>
<p>Yêu cầu: Xây dựng một chương trình cho phép nhập nội dung công việc và thời gian rồi list ra<br />
<strong><em><span style="text-decoration:underline;">B1:</span></em></strong> Vẫn bắt đầu bằng cách khởi tạo một Project mới: File -&gt; New -&gt; Android Project.<br />
Project name: Example 2<br />
Build Target: Chọn Android 1.5<br />
Application name: Example 2<br />
Package name: at.exam<br />
Create Activity: Example<br />
=&gt; Kích nút Finish.</p>
<p><strong><em><span style="text-decoration:underline;">B2:</span></em></strong> Đi tới res/main.xml để xây dựng giao diện cho chương trình:</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="590" valign="top">
<pre>&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    &gt;
    &lt;EditText
        android:id="@+id/work_enter"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:hint="@string/work_hint"
        android:lines="1"
        android:textSize="24px"
    /&gt;
    &lt;LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        &gt;
        &lt;TextView
            android:layout_width="50px"
            android:layout_height="wrap_content"
            android:text="@string/hour_edit"
            android:typeface="normal"
            android:textSize="15px"
            android:textStyle="bold"
            android:padding="5px"
        /&gt;
        &lt;EditText
            android:id="@+id/hour_edit"
            android:layout_width="45px"
            android:layout_height="wrap_content"
            android:hint="12"
            android:textColorHint="@color/hint_color"
            android:textSize="20px"
            android:gravity="center"
            android:padding="5px"
            android:numeric="integer"
            android:maxLength="2"
        /&gt;
        &lt;TextView
            android:layout_width="65px"
            android:layout_height="wrap_content"
            android:text="@string/minute_edit"
            android:typeface="normal"
            android:textSize="15px"
            android:textStyle="bold"
            android:padding="5px"
        /&gt;
        &lt;EditText
            android:id="@+id/minute_edit"
            android:layout_width="45px"
            android:layout_height="wrap_content"
            android:hint="00"
            android:textColorHint="@color/hint_color"
            android:textSize="20px"
            android:gravity="center"
            android:padding="5px"
            android:numeric="integer"
            android:maxLength="2"
        /&gt;       
    &lt;/LinearLayout&gt;
    &lt;Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="@string/button_content"
        /&gt;
    &lt;ListView
        android:id="@+id/list"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
    /&gt;
&lt;/LinearLayout&gt;</pre>
</td>
</tr>
</tbody>
</table>
<p>Giao diện ta thiết kế ở đây có 1 Linear Layout làm thành phần chính, các thành phần con của nó gồm 1 Edit Text (dùng để nhập nội dung công việc), 1 Linear Layout (lại gồm các thành phần con để nhập giờ và phút thực hiện công việc), 1 Button (để thêm nội dung công việc vào List View) và 1 List View dùng để list các công việc bạn đã nhập.<br />
Từ khóa lines được dùng để cố định số dòng và nên sử dụng với Edit Text thay vì dùng mỗi wrap_content vì nếu sd wrap_content thì Edit Text sẽ tự giãn ra nếu dòng nhập vào vượt giới hạn đường bao (làm hỏng giao diện bạn thiết kế).<br />
Từ khóa gravity thông báo các thành phần con sẽ được sắp xếp ntn ở thành phần cha. Ở đây mình dùng &#8220;center&#8221; nghĩa là thành phần con nằm ở trung tâm. Hãy thử thêm vào 1 Edit Text:</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="590" valign="top">
<pre>android:gravity="center"</pre>
</td>
</tr>
</tbody>
</table>
<p>Bạn sẽ thấy dòng chữ nhập vào sẽ bắt đầu từ giữa của Edit Text chứ không bắt đầu từ bên trái như trước nữa.<br />
Từ khóa padding dùng để cách 1 khoảng cách cho thành phần. Nếu không có padding thì 2 thành phần con thuộc cùng 1 LinearLayout sẽ được xếp sát nhau, nhưng nếu 1 thành phần con sử dụng padding thì sẽ tạo được khoảng cách với thành phần còn lại theo mong muốn. Ngoài ra còn có paddingLeft, paddingRight, paddingTop, paddingBottom.<br />
Từ khóa numeric dùng để giới hạn dạng ký tự nhập vào. Ở đây mình muốn chỉ nhập vào chữ số nên dùng &#8220;integer&#8221;<br />
Từ khóa maxLength dùng để giới hạn số ký tự nhập vào. Do Edit Text này dùng để nhập giờ nên maxLength=&#8221;2&#8243;.</p>
<p>Ok, giờ đến 1 chút kiến thức về các đơn vị của dimenson:<br />
- px (pixel): điểm chấm trên màn hình.<br />
- in (inch)<br />
- mm (milimet)<br />
- pt (point) = 1/72 m<br />
- dp (density &#8211; independent pixel): cái này hơi khó giải thích. Nói chung dp được sử dụng cho nhiều độ phân giải, và với độ phân giải 160 px/inch thì 1 dp = 1 px.<br />
- sp: gần giống dp, nên sử dụng cho text size.<br />
Nói chung nên sử dụng dp và sp để định nghĩa size cho các thành phần, vì nó có tỉ lệ cố định với độ phân giải của màn hình. Còn nếu bạn chủ tâm xây dựng cho 1 độ phân giải nhất định thì dùng px cho chính xác và chắc chắn.</p>
<p><strong><em><span style="text-decoration:underline;">B3:</span></em></strong> Tới values/strings.xml chỉnh sửa như sau:</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="590" valign="top"><code>&lt;?xml</code> <code>version="1.0"</code> <code>encoding="utf-8"?&gt;</code>&nbsp;</p>
<p><code>&lt;resources&gt;</code></p>
<p><code> &lt;string</code> <code>name="app_name"&gt;Example   2&lt;/string&gt;</code></p>
<p><code> &lt;string</code> <code>name="work_hint"&gt;Enter the   work here&lt;/string&gt;</code></p>
<p><code> &lt;string</code> <code>name="hour_edit"&gt;Hour&lt;/string&gt;</code></p>
<p><code> &lt;string</code> <code>name="minute_edit"&gt;Minute&lt;/string&gt;</code></p>
<p><code> &lt;string</code> <code>name="button_content"&gt;Add   work&lt;/string&gt;</code></p>
<p><code>&lt;/resources&gt;</code></td>
</tr>
</tbody>
</table>
<p><strong><em><span style="text-decoration:underline;">B4:</span></em></strong> Tạo mới colors.xml trong values với nội dung:</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="590" valign="top"><code>&lt;?xml</code> <code>version="1.0"</code> <code>encoding="utf-8"?&gt;</code>&nbsp;</p>
<p><code>&lt;resources&gt;</code></p>
<p><code> &lt;color</code> <code>name="hint_color"&gt;#cccccc&lt;/color&gt;</code></p>
<p><code>&lt;/resources&gt;</code></td>
</tr>
</tbody>
</table>
<p>OK, vậy là đã hoàn thiện phần giao diện. Các bạn có thể cho chạy thử ngay để kiểm tra xem giao diện đã như ý muốn chưa chứ không cần đợi hoàn thành cả code (Run as -&gt; Android Application).</p>
<p><strong><em><span style="text-decoration:underline;">B5:</span></em></strong> Time to coding. Tới thư mục src/Example.java và thay đổi nội dung file như sau:</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="590" valign="top"><code>package</code> <code>at.exam;</code>&nbsp;</p>
<p><code>import</code> <code>java.util.ArrayList;</code></p>
<p><code>import</code> <code>android.app.Activity;</code></p>
<p><code>import</code> <code>android.app.AlertDialog;</code></p>
<p><code>import</code> <code>android.content.DialogInterface;</code></p>
<p><code>import</code> <code>android.os.Bundle;</code></p>
<p><code>import</code> <code>android.view.View;</code></p>
<p><code>import</code> <code>android.view.View.OnClickListener;</code></p>
<p><code>import</code> <code>android.widget.ArrayAdapter;</code></p>
<p><code>import</code> <code>android.widget.Button;</code></p>
<p><code>import</code> <code>android.widget.EditText;</code></p>
<p><code>import</code> <code>android.widget.ListView;</code></p>
<p><code>public</code> <code>class</code> <code>Example extends</code> <code>Activity   {</code></p>
<p><code> /**   Called when the activity is first created. */</code></p>
<p><code> @Override</code></p>
<p><code> public</code> <code>void</code> <code>onCreate(Bundle savedInstanceState) {</code></p>
<p><code> super.onCreate(savedInstanceState);</code></p>
<p><code> setContentView(R.layout.main);</code></p>
<p><code> </code></p>
<p><code> //Tạo   mảng để chứa String nội dung công việc và giờ</code></p>
<p><code> final</code> <code>ArrayList&lt;String&gt; arrayWork = new</code> <code>ArrayList&lt;String&gt;();</code></p>
<p><code> //Adapter   dùng để kết nối mảng với List View</code></p>
<p><code> final</code> <code>ArrayAdapter&lt;String&gt; arrayAdapter   = new</code> <code>ArrayAdapter&lt;String&gt;(this, </code></p>
<p><code> android.R.layout.simple_list_item_1,   arrayWork);</code></p>
<p><code> </code></p>
<p><code> //Các   EditText để vào nội dung công việc được lấy về từ   XML </code></p>
<p><code> final</code> <code>EditText workEnter = (EditText)   findViewById(R.id.work_enter);</code></p>
<p><code> final</code> <code>EditText hourEdit = (EditText)   findViewById(R.id.hour_edit);</code></p>
<p><code> final</code> <code>EditText minuteEdit = (EditText)   findViewById(R.id.minute_edit);</code></p>
<p><code> </code></p>
<p><code> //Button   khi nhấn sẽ thêm công việc vào ListView</code></p>
<p><code> final</code> <code>Button button = (Button)   findViewById(R.id.button);</code></p>
<p><code> </code></p>
<p><code> //ListView   chứa danh sách công việc</code></p>
<p><code> final</code> <code>ListView list = (ListView)   findViewById(R.id.list);</code></p>
<p><code> //Cần   set Adapter cho list để biết sẽ lấy nội dung từ mảng arrayWork</code></p>
<p><code> list.setAdapter(arrayAdapter);</code></p>
<p><code> </code></p>
<p><code> //Định   nghĩa Listener xử lý sự kiện nhấn vào button</code></p>
<p><code> OnClickListener   add = new</code> <code>OnClickListener()   {</code></p>
<p><code> @Override</code></p>
<p><code> public</code> <code>void</code> <code>onClick(View v) {</code></p>
<p><code> //Nếu   1 trong 3 Edit Text không có nội dung thì hiện lên cảnh báo</code></p>
<p><code> if</code> <code>(workEnter.getText().toString().equals("")   ||</code></p>
<p><code> hourEdit.getText().toString().equals("")   ||</code></p>
<p><code> minuteEdit.getText().toString().equals(""))   { </code></p>
<p><code> AlertDialog.Builder   builder = new</code> <code>AlertDialog.Builder(Example.this);</code></p>
<p><code> builder.setTitle("Info   missing");</code></p>
<p><code> builder.setMessage("Please   enter all information of the work");</code></p>
<p><code> builder.setPositiveButton("Continue",   new</code> <code>DialogInterface.OnClickListener()   {</code></p>
<p><code> public</code> <code>void</code> <code>onClick(DialogInterface dialog, int</code> <code>which) {</code></p>
<p><code> //   TODO Auto-generated method   stub </code></p>
<p><code> } </code></p>
<p><code> });</code></p>
<p><code> builder.show();</code></p>
<p><code> }</code></p>
<p><code> //Lấy   nội dung công việc và thời gian ra từ Edit Text và đưa vào list</code></p>
<p><code> else</code> <code>{</code></p>
<p><code> String   str = workEnter.getText().toString() + " - "</code></p>
<p><code> +   hourEdit.getText().toString() + ":"</code></p>
<p><code> +   minuteEdit.getText().toString();</code></p>
<p><code> arrayWork.add(0,str);</code></p>
<p><code> arrayAdapter.notifyDataSetChanged();</code></p>
<p><code> workEnter.setText("");</code></p>
<p><code> hourEdit.setText("");</code></p>
<p><code> minuteEdit.setText("");</code></p>
<p><code> }</code></p>
<p><code> }</code></p>
<p><code> </code></p>
<p><code> };</code></p>
<p><code> </code></p>
<p><code> //set   Listener cho button</code></p>
<p><code> button.setOnClickListener(add); </code></p>
<p><code> }</code></p>
<p><code>}</code></td>
</tr>
</tbody>
</table>
<p>Mình đã chú thích đầy đủ và đoạn code cũng khá dễ hiểu. Tuy nhiên cần lưu ý 2 vấn đề ở đây.<br />
- Khởi tạo đối tượng ArrayAdapter: Các bạn thấy đối số truyền vào là <strong><em>(this, android.R.layout.simple_list_item_1, arrayWork)</em></strong>. This là đối số của lớp Context (ở đây chính là activity Example). Bạn sẽ gặp Context trong rất nhiều khởi tạo các lớp và nên hiểu Context có ý nghĩa gì.</p>
<ul>
<li>Context      thuộc <strong><em>android.content </em></strong><em>(android.content.Context)</em>.</li>
<li>Là một      Interface (lớp giao tiếp) chứa hầu hết thông tin về môi trường ứng dụng      của android, có nghĩa là mọi thao tác, tương tác với hệ điều hành điều      phải qua lớp này.</li>
<li>Nó là      một lớp abstract (trừu tượng) cung cấp cho những lớp khác các phương thức      để tương tác với hệ thống Android.</li>
<li>Nó cho      phép truy cập tới các nguồn tài nguyên (resources) đã được định nghĩa và      các lớp khác. Ví dụ như nó có thể khởi tạo và chạy các activities, các      broadcast và các intents,&#8230; Chúng ta coi như Contex là một lớp ở mức ứng      dụng (Application level- liên quan tới hệ thống).</li>
<li>Tóm      lại context giúp chúng ta dễ dàng truy cập và tương tác tới các tài nguyên      của hệ thống, các thông tin, các dịch vụ (services), các thông số cấu      hình, database, wallpaper, danh bạ, cuộc gọi, kết nối, chế độ rung      (vibrator).</li>
<li>Sở dĩ      hầu hết các lớp có liên quan tới UI (layout, button, textview, imageview,      listview,&#8230;) đều pải super tới Context vì bản thân nó đảm nhiệm việc truy      cập resource (R.id, R.layout,&#8230;.). Nếu chúng ta không tham chiếu tới      Context class thì đương nhiên không thể dùng tới các resources mà chúng ta      đã tạo ra.</li>
</ul>
<p>Tiếp theo là android.R.layout.simple_list_item_1, đối này định nghĩa cách thể hiện item (ở đây là String) trong List View. Các bạn hãy ghi nhớ android.R.* là các tài nguyên (resource) có sẵn của Android cho phép bạn truy cập và sử dụng. Sau này khi hướng dẫn tạo custom View cho List View mình sẽ đề cập lại vấn đề này.<br />
Cuối cùng arrayWork chính là mảng cần được bind của adapter.</p>
<p>- AlertDialog là lớp cho phép đưa ra 1 hộp thoại, thường dùng để đưa ra thông tin hoặc cảnh báo đơn giản. Trong code mình tạo 1 builder, tạo tiêu đề (title) cho nó, đưa ra thông báo (message) và cuối cùng là tạo 1 positive button (nhưng không định nghĩa xử lý khi nhấn nút này, vì vậy nếu bạn nhấn nút thì dialog sẽ chỉ đơn giản thực hiện việc đóng lại).</p>
<p><strong><em><span style="text-decoration:underline;">B6:</span></em></strong> Tiến hành chạy thử chương trình. Run as -&gt; Android Application.</p>
<p>Tham khảo từ: http://diendan.vietandroid.com/ca-c-ba-i-ha-c-ca-ka-m-ma-ngua-n/409-hae-ng-da-n-la-p-tra-nh-cae-ba-n-va-i-android-ba-i-2-a.html.</p>
<p>Các bài liên quan:<br />
<a href="http://mobilesprogramming.wordpress.com/2011/03/20/c%C6%A1-b%E1%BA%A3n-android-h%C6%B0%E1%BB%9Bng-d%E1%BA%ABn-l%E1%BA%ADp-trinh-c%C6%A1-b%E1%BA%A3n-tren-android-p2/">Cơ bản trên Android</a>.</p>
<p><a href="http://mobilesprogramming.wordpress.com/2011/03/30/c%C6%A1-b%E1%BA%A3n-android-viewgroup-va-custom-adapter-p4/">Viewgroup và custom Adapter &#8211; P4</a></p>
<br />Filed under: <a href='http://mobilesprogramming.wordpress.com/category/android/'>Android</a>, <a href='http://mobilesprogramming.wordpress.com/category/android/android-tutorial/'>Android Tutorial</a> Tagged: <a href='http://mobilesprogramming.wordpress.com/tag/android-2/'>android</a>, <a href='http://mobilesprogramming.wordpress.com/tag/android_basic/'>android_basic</a>, <a href='http://mobilesprogramming.wordpress.com/tag/android_tutorial/'>android_tutorial</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mobilesprogramming.wordpress.com/796/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mobilesprogramming.wordpress.com/796/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mobilesprogramming.wordpress.com/796/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mobilesprogramming.wordpress.com/796/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/mobilesprogramming.wordpress.com/796/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/mobilesprogramming.wordpress.com/796/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/mobilesprogramming.wordpress.com/796/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/mobilesprogramming.wordpress.com/796/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mobilesprogramming.wordpress.com/796/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mobilesprogramming.wordpress.com/796/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mobilesprogramming.wordpress.com/796/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mobilesprogramming.wordpress.com/796/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mobilesprogramming.wordpress.com/796/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mobilesprogramming.wordpress.com/796/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mobilesprogramming.wordpress.com&amp;blog=11410337&amp;post=796&amp;subd=mobilesprogramming&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mobilesprogramming.wordpress.com/2011/03/24/c%c6%a1-b%e1%ba%a3n-android-%e2%80%93h%c6%b0%e1%bb%9bng-d%e1%ba%abn-l%e1%ba%adp-trinh-c%c6%a1-b%e1%ba%a3n-v%e1%bb%9bi-android-p3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/992f5fba26e8af9ebb4a25d922f208c6?s=96&#38;d=&#38;r=G" medium="image">
			<media:title type="html">mobilesprogramming</media:title>
		</media:content>
	</item>
		<item>
		<title>Cơ Bản Android &#8211; Cơ Bản Trên Android &#8211; P2</title>
		<link>http://mobilesprogramming.wordpress.com/2011/03/20/c%c6%a1-b%e1%ba%a3n-android-h%c6%b0%e1%bb%9bng-d%e1%ba%abn-l%e1%ba%adp-trinh-c%c6%a1-b%e1%ba%a3n-tren-android-p2/</link>
		<comments>http://mobilesprogramming.wordpress.com/2011/03/20/c%c6%a1-b%e1%ba%a3n-android-h%c6%b0%e1%bb%9bng-d%e1%ba%abn-l%e1%ba%adp-trinh-c%c6%a1-b%e1%ba%a3n-tren-android-p2/#comments</comments>
		<pubDate>Sun, 20 Mar 2011 16:11:00 +0000</pubDate>
		<dc:creator>mobilesprogramming</dc:creator>
		
		<guid isPermaLink="false">http://mobilesprogramming.wordpress.com/?p=789</guid>
		<description><![CDATA[I.Yêu Cầu Kiến Thức Cho Lập Trình Android Để lập trình android, mình nghĩ mọi người chỉ cần kiến thức java căn bản là hoàn toàn ok. Căn bản ở đây có nghĩa là hiểu được thế nào là class, package, biết ý nghĩa của các từ khóa như public, private, protected,&#8230; thành thạo các [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mobilesprogramming.wordpress.com&amp;blog=11410337&amp;post=789&amp;subd=mobilesprogramming&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<h2>I.Yêu Cầu Kiến Thức Cho Lập Trình Android</h2>
<ul>
<li>Để lập      trình android, mình nghĩ mọi người chỉ cần kiến thức java căn bản là hoàn      toàn ok. Căn bản ở đây có nghĩa là hiểu được thế nào là class, package,      biết ý nghĩa của các từ khóa như public, private, protected,&#8230; thành thạo      các lệnh cơ bản như if, for(), switch(), while(), &#8230; biết sử dụng các      lệnh như Integer.parseInt() hay String.valueOf()&#8230; Nên có thêm kiến thức      về gói java.util vì đây là gói hỗ trợ nhiều lớp rất mạnh được sử dụng trên      mọi nền, ngoài ra các gói như java.io, java.net&#8230; cũng được quan tâm.</li>
<li>Các      kiến thức về các gói lập trình cho desktop như java.awt, java.swing hoàn      toàn không cần thiết (bản thân mình cũng chưa sử dụng cái này bao giờ,      nhảy vào học java là học J2ME luôn), hay các gói của J2ME cũng vậy. Lập      trình Android tuy cũng là lập trình di động, nhưng các điện thoại sử dụng      hệ điều hành Android có cấu hình rất mạnh (Nexus One có VXL lên tới 1Ghz),      vì vậy 2 nền tảng Android và J2ME cũng rất khác nhau. Android có những gói      riêng hỗ trợ lập trình cho nó và không yêu cầu khắt khe về việc tối ưu      code như J2ME. Thật đáng tiếc vì J2ME mình học không ứng dụng được mấy vào      lập trình Android (tuy nhiên 1 số kỹ thuật cơ bản cho lập trình game 2D      như Sprite, double buffering, Tile&#8230; thì vẫn không hề phí phạm chút nào).</li>
</ul>
<h2>II.Cài Đặt Android Để Lập Trình</h2>
<ul>
<li>Để lập trình Android thì mỗi bộ SDK của Google là không đủ, bạn còn cần tích hợp nó vào một IDE như Eclipse. Anh Giáp đã có 2 bài hướng dẫn rất chi tiết về cài đặt Android trong Eclipse cũng như Netbeans, nhưng theo mình mọi người nên sử dụng Eclipse hơn vì nó có nhiều tính năng hỗ trợ lập trình Google, còn Netbeans thì plugin cho Android vẫn chưa hoàn thiện.</li>
<li>Tiện thể mình nói luôn, mình học Android theo 2 cuốn <em>Professional Android Application Development</em> và <em>Unlocking Android</em>. Cả 2 cuốn đều dành cho beginner nhưng cuốn đầu code nhiều, giải thích ít, cuốn thứ 2 giải thích rõ ràng hơn. Nếu có ai có ý định tham khảo thì nên đọc cuốn UA trước để hiểu rõ hơn Android, sử dụng cuốn PAAD trong việc tham khảo các đoạn code cho lập trình.<span id="more-789"></span></li>
</ul>
<h2>III.Understanding Android Application</h2>
<p>Việc hiểu được các thành phần (component) tạo nên một ứng dụng Android là rất cần thiết cho việc lập trình. Các thành phần này được chia làm 6 loại bao gồm:</p>
<h3>1.Activity</h3>
<p>Hiểu một cách đơn giản thì Activity là nền của 1 ứng dụng. Khi khởi động 1 ứng dụng Android nào đó thì bao giờ cũng có 1 main Activity được gọi, hiển thị màn hình giao diện của ứng dụng cho phép người dùng tương tác.</p>
<h3>2.Service</h3>
<p>Thành phần chạy ẩn trong Android. Service sử dụng để update dữ liệu, đưa ra các cảnh báo (Notification) và không bao giờ hiển thị cho người dùng thấy.</p>
<h3>3.Content Provider</h3>
<p>Kho dữ liệu chia sẻ. Content Provider được sử dụng để quản lý và chia sẻ dữ liệu giữa các ứng dụng.</p>
<h3>4.Intent</h3>
<p>Nền tảng để truyền tải các thông báo. Intent được sử dụng để gửi các thông báo đi nhằm khởi tạo 1 Activity hay Service để thực hiện công việc bạn mong muốn. VD: khi mở 1 trang web, bạn gửi 1 intent đi để tạo 1 activity mới hiển thị trang web đó.</p>
<h3>5.Broadcast Provider</h3>
<p>Thành phần thu nhận các Intent bên ngoài gửi tới. VD: bạn viết 1 chương trình thay thế cho phần gọi điện mặc định của Android, khi đó bạn cần 1 BR để nhận biết các Intent là các cuộc gọi tới.</p>
<h3>6.Notification</h3>
<p>Đưa ra các cảnh báo mà không làm cho các Activity phải ngừng hoạt động.</p>
<p><strong>Lưu ý</strong> Activity, Service, Broadcast Receiver và Content Provider mới là những thành phần chính cấu thành nên ứng dụng Android, bắt buộc phải khai báo trong AndroidManifest (tham khảo bài tiếp theo có giới thiệu đầy đủ về file này).</p>
<h2>IV.Understanding Android Application Life Cycle</h2>
<p>Android có cơ chế quản lý các process theo chế độ ưu tiên. Các process có priority thấp sẽ bị Android giải phóng mà không hề cảnh báo nhằm đảm bảo tài nguyên.</p>
<ul>
<li><strong><em>Foreground process:</em></strong> là process của ứng dụng hiện thời đang được người dùng tương tác.</li>
<li><strong><em>Visible process:</em></strong> là process của ứng dụng mà activity đang hiển thị đối với người dùng (onPaused() của activity được gọi).</li>
<li><strong><em>Service process:</em></strong> là Service đang running.</li>
<li><strong><em>Background process:</em></strong> là process của ứng dụng mà các activity của nó ko hiển thị với người dùng (onStoped() của activity được gọi).</li>
<li><strong><em>Empty process:</em></strong> process không có bất cứ 1 thành phần nào active.<br />
Theo chế độ ưu tiên thì khi cần tài nguyên, Android sẽ tự động kill process, trước tiên là các empty process.</li>
</ul>
<h3>1.Android Activity Life Cycle</h3>
<p>Như đã giới thiệu ở trên, Actitvity là thành phần quan trọng nhất và đóng vai trò chính trong xây dựng ứng dụng Android. Hệ điều hành Android quản lý Activity theo dạng stack: khi một Activity mới được khởi tạo, nó sẽ được xếp lên đầu của stack và trở thành <em><strong>running activity</strong></em>, các Activity trước đó sẽ bị tạm dừng và chỉ hoạt động trở lại khi Activity mới được giải phóng.Activity bao gồm 4 state:</p>
<ul>
<li><strong><em>active (running):</em></strong> Activity đang hiển thị trên màn hình (foreground).</li>
<li><strong><em>paused:</em></strong> Activity vẫn hiển thị (visible) nhưng không thể tương tác (lost focus). VD: một activity mới xuất hiện hiển thị giao diện đè lên trên activity cũ, nhưng giao diện này nhỏ hơn giao diện của activity cũ, do đó ta vẫn thấy được 1 phần giao diện của activity cũ nhưng lại không thể tương tác với nó.</li>
<li><strong>· </strong><strong><em>stop:</em></strong> Activity bị thay thế hoàn toàn bởi Activity mới sẽ tiến đến trạng thái <strong><em>stop.</em></strong><strong></strong></li>
<li><strong><em>killed:</em></strong> Khi hệ thống bị thiếu bộ nhớ, nó sẽ giải phóng các tiến trình theo nguyên tắc ưu tiên. Các Activity ở trạng thái <strong><em>stop</em></strong> hoặc <strong><em>paused</em></strong> cũng có thể bị giải phóng và khi nó được hiển thị lại thì các Activity này phải khởi động lại hoàn toàn và phục hồi lại trạng thái trước đó.</li>
</ul>
<h3>2.Biểu Đồ Miêu Tả Activity State</h3>
<p><a href="http://mobilesprogramming.files.wordpress.com/2011/03/bai2_img1.png"><img class="aligncenter size-medium wp-image-790" title="Bai2_img1" src="http://mobilesprogramming.files.wordpress.com/2011/03/bai2_img1.png?w=229&#038;h=300" alt="" width="229" height="300" /></a></p>
<h3>3.Vòng đời của Activity</h3>
<ul>
<li><strong>· </strong><em><strong>Entire lifetime:</strong></em> Từ phương thức <strong>onCreate()</strong> cho tới <strong>onDestroy().</strong><strong></strong></li>
<li><strong>· </strong><em><strong>Visible liftetime:</strong></em> Từ phương thức <strong>onStart()</strong> cho tới <strong>onStop().</strong><strong></strong></li>
<li><em><strong>Foreground lifetime:</strong></em> Từ phương thức <strong>onResume()</strong> cho tới <strong>onPause().</strong></li>
</ul>
<p>Khi xây dựng Actitvity cho ứng dụng cần phải viết lại phương thức <strong>onCreate( )</strong> để thực hiện quá trình khởi tạo. Các phương thức khác có cần viết lại hay không tùy vào yêu cầu lập trình.</p>
<h3>4.XML trong Android</h3>
<ul>
<li>Không giống như lập trình java thông thường, lập trình android ngoài các lớp được viết trong *.java còn sử dụng XML để thiết kế giao diện cho ứng dụng. Tất nhiên bạn hoàn toàn có thể thiết kế 1 giao diện như ý muốn mà không cần tới bất cứ 1 dòng XML nào, nhưng sử dụng XML sẽ đơn giản công việc đi rất nhiều.</li>
<li>Đồng thời sd XML sẽ giúp việc chỉnh sửa ứng dụng sau này trở nên dễ dàng.<br />
Về nguyên tắc, khi lập trình ứng dụng ta thiết kế giao diện bằng XML và cài đặt các xử lý khi tương tác với giao diện trong code.</li>
</ul>
<h2>V.Một Số Thành Phần Cơ Bản Trong Android</h2>
<h3>1.Các Layout</h3>
<p>Layout được dùng để quản lý các thành phần giao diện khác theo 1 trật tự nhất định.</p>
<ul>
<li><strong>FrameLayout:</strong> Layout đơn giản nhất, thêm các thành phần con vào góc trên bên trái của màn hình.</li>
<li><strong>LinearLayout:</strong> thêm các thành phần con theo 1 chiều nhất định (ngang hoặc dọc). Đây là layout được sử dụng nhiều nhất.</li>
<li><strong>RelativeLayout:</strong> thêm các thành phần con dựa trên mối quan hệ với các thành phần khác hoặc với biên của layout.</li>
<li><strong>TableLayout:</strong> thêm các thành phần con dựa trên 1 lưới các ô ngang và dọc.</li>
<li><strong>AbsoluteLayout:</strong> thêm các thành phần con dựa theo tọa độ x, y.</li>
</ul>
<p>Layout được sử dụng nhằm mục đích thiết kế giao diện cho nhiều độ phân giải. Thường khi lập trình nên kết hợp nhiều layout với nhau để tạo ra giao diện bạn mong muốn.</p>
<h3>2.XML Unit</h3>
<p>Để hiểu được các thành phần cơ bản của XML cũng như việc sử dụng XML kết hợp với code, ta sẽ đi xây dựng thử một chương trình đơn giản.</p>
<p>Yêu cầu: Xây dựng 1 ứng dụng cho phép gõ 1 nội dung vào rồi hiển thị ra nội dung đó ở bên dưới.</p>
<p><strong><em>B1:</em></strong> Khởi tạo 1 project (ở đây sử dụng Eclipse để minh họa).<br />
Vào thẻ <strong>File</strong> -&gt; <strong>New</strong> -&gt; <strong>Android Project</strong>. Nếu bạn mới lập trình Android lần đầu thì có lẽ dòng Android Project sẽ không hiện ra, khi đó xuống phía cuối chọn <strong>Other</strong> rồi vào <strong>Android</strong> -&gt; <strong>Android Project</strong>.</p>
<p><strong><em>B2:</em></strong> Điền thông tin cho project</p>
<ul>
<li>Project name: Example 1</li>
<li>Build Target: Chọn Android 1.5 (mới nhất là 2.1 nhưng hiện tại bạn chưa cần quan tâm).</li>
<li>Application name: Example 1</li>
<li>Package name: at.exam</li>
<li>Create Activity: Example</li>
<li>Kích nút Finish.</li>
</ul>
<p><strong><em>B3:</em></strong> Bên khung <strong>Package Explore</strong> bên trái đi tới thư mục res, bạn sẽ thấy có 3 thư mục con:</p>
<ul>
<li>drawable: thư mục chứa các hình ảnh để làm icon hoặc tài nguyên cho giao diện&#8230;</li>
<li>layout: chứa các file xml để thiết kế giao diện.</li>
<li>values: chứa các giá trị sử dụng trong ứng dụng được bạn định nghĩa, như các dòng ký tự (string), các màu (color), các themes&#8230;</li>
</ul>
<p><em><strong><span style="text-decoration:underline;">B4:</span></strong></em>Vào thư mục layout, chọn file main.xml và gõ đoạn code sau vào thay cho toàn bộ nội dung có sẵn (Eclipse hỗ trợ kéo thả cho xml nhưng theo mình không nên sử dụng).</p>
<p>Mã:</p>
<div>
<pre>&lt;?xml version="1.0" encoding="utf-8"?&gt;

&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:orientation="vertical"

    android:layout_width="fill_parent"

    android:layout_height="fill_parent"

    &gt;

    &lt;EditText

        android:id="@+id/edit_text"

        android:layout_width="fill_parent"

        android:layout_height="wrap_content"

        android:hint="@string/edit_hint"

    /&gt;

    &lt;TextView  

        android:id="@+id/text_view"

        android:layout_width="fill_parent" 

        android:layout_height="wrap_content"

        android:textColor="@color/text_color"

        android:textSize="28px"

        android:typeface="monospace"

    /&gt;

&lt;/LinearLayout&gt;</pre>
</div>
<ul>
<li>Trong đoạn XML này chúng ta khai báo một Linear Layout với 2 thành phần con của nó là 1 Edit Text (dùng để gõ xâu ký tự) với 1 Text View (hiển thị xâu ký tự). Linear Layout được khai báo với từ khóa orientation nhằm chỉ ra chiều sắp xếp của 2 thành phần con là chiều dọc. Còn với layout_width, layout_height các bạn có thể cho giá trị bằng &#8220;fill_parent&#8221; hoặc &#8220;wrap_content&#8221; để thông báo thành phần này sẽ có chiều rộng (dài) phủ đầy thành phần cha hoặc chỉ vừa bao đủ nội dung.<br />
Trong Edit Text và Text View các bạn có thể thấy có từ khóa id, từ khóa này cho phép khai báo id của các thành phần để lấy về trong code (sẽ đề cập sau).</li>
<li>Ngoài ra từ khóa hint trong Edit Text cho phép hiện ra phần nội dung mờ khi Edit Text vẫn chưa có ký tự nào. &#8220;@string/edit_hint&#8221; thông báo lấy trong file strings.xml xâu có tên là edit_hint.</li>
<li>Còn textColor của Text View thì thông báo đoạn ký tự sẽ được hiển thị với màu lấy trong file colors.xml, textSize chỉ ra cỡ chữ bằng 28 pixel và typeface chỉ ra kiểu chữ là monospace.</li>
</ul>
<p><strong><em>B5:</em></strong>Vẫn trong thư mục res, vào values và chọn file strings.xml. Bố sung thêm dòng định nghĩa cho edit_hint như sau:</p>
<p>Mã:</p>
<div>
<pre>&lt;?xml version="1.0" encoding="utf-8"?&gt;

&lt;resources&gt;

    &lt;string name="hello"&gt;Hello World, Example!&lt;/string&gt;

    &lt;string name="app_name"&gt;Example 1&lt;/string&gt;

    &lt;string name="edit_hint"&gt;Enter the work here&lt;/string&gt;

&lt;/resources&gt;</pre>
</div>
<p>vào thư mục src (source code của project) =&gt; at.exam =&gt; Example.java, gõ nội dung code sau vào:</p>
<p>Mã:</p>
<div>
<pre>package at.exam;

import android.app.Activity;

import android.os.Bundle;

import android.view.KeyEvent;

import android.view.View;

import android.view.View.OnKeyListener;

import android.widget.EditText;

import android.widget.TextView;

public class Example extends Activity {

    /** Called when the activity is first created. */

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        //Thiết lập giao diện lấy từ file main.xml

        setContentView(R.layout.main);

        //Lấy về các thành phần trong main.xml thông qua id

        final EditText edit = (EditText) findViewById(R.id.edit_text);

        final TextView text = (TextView) findViewById(R.id.text_view);

        //Thiết lập xử lý cho sự kiện nhấn nút giữa của điện thoại

        edit.setOnKeyListener(new OnKeyListener() {            

            @Override

            public boolean onKey(View v, int keyCode, KeyEvent event) {

                if (event.getAction() == KeyEvent.ACTION_DOWN 

                        &amp;&amp; keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {

                    text.setText(edit.getText().toString());

                    edit.setText("");

                    return true;                    

                }

                else {

                    return false;

                }

            }

        });

    }

}</pre>
</div>
<p>Dạo qua một chút kiến thức cơ bản: Trong Android, các lớp sử dụng để tạo giao diện (Edit Text, Text View&#8230;) đều là lớp con của lớp View. Một số lớp thường xuyên được sử dụng để tạo giao diện:</p>
<ul>
<li>TextView</li>
<li>EditText</li>
<li>ListView</li>
<li>Spinner</li>
<li>CheckBox</li>
<li>Button</li>
<li>RadioButton</li>
</ul>
<p>Ngoài ra bạn còn có thể tạo 1 View riêng của mình bằng cách kế thừa View có sẵn.</p>
<p>Các Listener được sử dụng để bắt 1 sự kiện nào đó. Ở đây mình sử dụng OnKeyListener dùng để bắt sự kiện khi nhấn 1 phím của điện thoại. Ngoài ra thường sử dụng OnClickListener để bắt sự kiện chạm vào 1 View đang hiển thị trên màn hình. Mỗi View đều phải set Listener riêng để xử lý cho sự kiện tương tác với nó, và mỗi loại View cũng lại có những Listener dành riêng cho nó (VD: CheckBox có OnCheckChangedListener)<br />
Ở đây mình sử dụng hàm dạng inner để định nghĩa xử lý cho OnKeyListener nên có thể mọi người không quen lắm, nhưng nó cũng nằm trong phần cơ bản của Java đấy nhé.</p>
<p>Đề nghị lưu ý thêm phần R.id.edit_text. Để lấy hoặc truy nhập các thành phần ta đã định nghĩa trong XML ta phải sử dụng R.* như R.layout.main, R.id.edit_text. Lệnh findViewById sẽ trả về 1 View có Id thiết lập trong phần XML. Do View là lớp cha của EditText với TextView nên ở đây ta phải ép kiểu.</p>
<p>Ngoài ra các string hay color cũng có thể lấy về bằng lệnh getResource(). Vd: getResource().getColor(R.color.text_color).</p>
<p><strong><em>B8:</em></strong> Chạy chương trình. Chọn Run =&gt; Android Application và chờ cho emulator khởi động nhé. Ai có 1 Android thật có thể kết nối qua USB và thử nghiệm luôn. Tự chỉnh sửa trong code và trong XML để hiểu thêm về lập trình Android.<br />
Mã:</p>
<div>
<pre>edit.setOnClickListener(new OnClickListener() {            

                        @Override

            public void onClick(View v) {

                // TODO Auto-generated method stub

            }

        });</pre>
</div>
<p>hoặc trong XML thêm vào phần Text View</p>
<p>Mã:</p>
<div>
<pre>android:textSize="50px"</pre>
</div>
<p style="text-align:right;">Tham khảo từ: VietAndroid.</p>
<p>Các bài viết liên quan:<br />
<a href="http://mobilesprogramming.wordpress.com/2011/03/15/c%C6%A1-b%E1%BA%A3n-android-tich-h%E1%BB%A3p-android-vao-eclipse-ph%E1%BA%A7n-1/">Tích Hợp Android Vào Eclipse</a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mobilesprogramming.wordpress.com/789/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mobilesprogramming.wordpress.com/789/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mobilesprogramming.wordpress.com/789/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mobilesprogramming.wordpress.com/789/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/mobilesprogramming.wordpress.com/789/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/mobilesprogramming.wordpress.com/789/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/mobilesprogramming.wordpress.com/789/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/mobilesprogramming.wordpress.com/789/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mobilesprogramming.wordpress.com/789/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mobilesprogramming.wordpress.com/789/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mobilesprogramming.wordpress.com/789/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mobilesprogramming.wordpress.com/789/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mobilesprogramming.wordpress.com/789/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mobilesprogramming.wordpress.com/789/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mobilesprogramming.wordpress.com&amp;blog=11410337&amp;post=789&amp;subd=mobilesprogramming&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mobilesprogramming.wordpress.com/2011/03/20/c%c6%a1-b%e1%ba%a3n-android-h%c6%b0%e1%bb%9bng-d%e1%ba%abn-l%e1%ba%adp-trinh-c%c6%a1-b%e1%ba%a3n-tren-android-p2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/992f5fba26e8af9ebb4a25d922f208c6?s=96&#38;d=&#38;r=G" medium="image">
			<media:title type="html">mobilesprogramming</media:title>
		</media:content>

		<media:content url="http://mobilesprogramming.files.wordpress.com/2011/03/bai2_img1.png?w=229" medium="image">
			<media:title type="html">Bai2_img1</media:title>
		</media:content>
	</item>
		<item>
		<title>Notepad Example &#8211; Phần 1</title>
		<link>http://mobilesprogramming.wordpress.com/2011/03/16/notepad-example-ph%e1%ba%a7n-1/</link>
		<comments>http://mobilesprogramming.wordpress.com/2011/03/16/notepad-example-ph%e1%ba%a7n-1/#comments</comments>
		<pubDate>Wed, 16 Mar 2011 04:37:24 +0000</pubDate>
		<dc:creator>mobilesprogramming</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Android Tutorial]]></category>
		<category><![CDATA[android_basic]]></category>
		<category><![CDATA[android_tutorial]]></category>

		<guid isPermaLink="false">http://mobilesprogramming.wordpress.com/?p=780</guid>
		<description><![CDATA[NotePad Exercise 1 Trong bài tập này, bạn sẽ construct một notes list đơn giãn cho phép user thêm mới các notes nhưng không được edit chúng. Trong bài này, chúng ta sẽ làm hiểu các phần cơ bản sau: Cơ bản về ListActivity, tạo và xử lý menu options. Sử dụng SQLite database để [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mobilesprogramming.wordpress.com&amp;blog=11410337&amp;post=780&amp;subd=mobilesprogramming&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<div>
<h1>NotePad Exercise 1</h1>
</div>
<p>Trong bài tập này, bạn sẽ construct một notes list đơn giãn cho phép user thêm mới các notes nhưng không được edit chúng. Trong bài này, chúng ta sẽ làm hiểu các phần cơ bản sau:</p>
<ul>
<li>Cơ      bản về ListActivity, tạo và xử lý menu options.</li>
<li>Sử      dụng SQLite database để lưu trữ các notes.</li>
<li>Bind      dữ liệu từ một database cursor vào một ListView sử dụng một      SimpleCursorAdapter.</li>
<li>Cơ      bản về screen layout (layout một list view), thêm các item vào activity      menu, và cách thức activity xử lý các selection cho menu.</li>
</ul>
<p>Trước khi bắt đầu, bạn vào đây để download <a href="http://developer.android.com/resources/tutorials/notepad/index.html#preparing">bài tập</a> có chứa NotepadCodeLab.</p>
<h2>I.Step 1</h2>
<ul>
<li><strong>B1.</strong>Trong Eclipse, click vào <strong>File-&gt;New-&gt;Android Project</strong>.</li>
<li><strong>B2.</strong>Chọn <strong>Create project from existing source</strong>.</li>
<li><strong>B3.</strong>Click <strong>Browse</strong> và navigate đến nơi có chứa thư mục NotepadCodeLab và chọn Notepadv1.</li>
<li><strong>B4.</strong>Click <strong>Finish</strong>.</li>
</ul>
<h2>II.Step 2</h2>
<ul>
<li>Sau      khi tạo project Notepadv1, bạn sẽ thấy lớp NotesDbAdapter      – lớp này được cung cấp để đóng gói dữ liệu truy cập vào SQLite database      mà sẽ nắm giữ các notes data và cho phép bạn cập nhật nó.</li>
<li>Ở phía trên của lớp là một số định nghĩa constant sẽ được sử dụng trong ứng      dụng để tìm kiếm dữ liệu từ các      tên trường thích      hợp trong database.</li>
<li>Tên      của database là “data” và tên của table là      “notes” gồm có 3 field: _id, title và body.</li>
<li>Constructor      của NotesDbAdapter có chứa một Context,      cho phép nó giao tiếp với các khía cạnh của OS Android. Lớp Activity      implement lớp Context, vì vậy bạn thường sẽ sử dụng từ khóa “this” từ Activity, khi cần một Context.</li>
<li>Phương      thức open() gọi một thể hiện của lớp DatabaseHelper (lớp này được cài đặt cục bộ      trong lớp NotesDbAdapter và kết thừa từ SQLiteOpenHelper). Nó gọi getWritableDatabase() để xử lý việc tạo và mở      database cho bạn.</li>
<li>Phương      thức createNote() có chứa các string cho      title và body của một note mới, sau đó tạo note đó trong database. Giả sử      note mới được tạo ra thành công, phương thức này cũng trả về giá trị _id cho note mới được tạo ra.</li>
<li>Phương      thức deleteNote() có chứa một rowId cho một note cụ thể, và xóa note đó từ      database.</li>
<li>Phương      thức fetchAllNote() thực hiện truy vấn và      trả về một Cursor cho tất cả các note trong database, đó là nó gọi phương      thức query(). Trong phương thức query(), tham số đầu tiên là tên của database      table để truy vấn (trong ví dụ này, DATABASE_TABLE      là “notes”), tham số tiếp theo là danh      sách các column mà bạn muốn trả về, trong ví dụ này đó là các column: _id, title, và body, vì vậy chúng được xác định là một mảng      String. Các tham số thiếp theo lần lượt là: selection,      selectionArgs, groupBy,      having và orderBy;      giá trị của having bằng null, có nghĩa là      bạn muốn tất cả data, không cần group chúng và có thứ tự mặc định. Xem      thêm <a href="http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#query%28java.lang.String,%20java.lang.String[],%20java.lang.String,%20java.lang.String[],%20java.lang.String,%20java.lang.String,%20java.lang.String%29">SQLiteDatabase</a>.</li>
<li><strong>Lưu ý</strong>: Một Cursor được trả về chứ không phải là một collection      của các row. Điều      này cho phép Android sử dụng các resource một cách hiệu quả &#8211; thay      vì put các dữ liệu trực tiếp vào bộ nhớ, con trỏ sẽ retrieve và release dữ liệu khi cần thiết, điều này hiệu quả hơn nhiều việc sử dụng các table      có chứa nhiều row.</li>
<li>Phương      thức fetchNote() tương tự như fetchAllNote() nhưng chỉ nhận một note với rowId.</li>
<li>Cuối      cùng, phương thức updateNote() có chứa rowId, title và body, và sử dụng một thể hiện của ContentValues để cập nhật note của rowId cho trước.<span id="more-780"></span></li>
</ul>
<h2>III.Step 3</h2>
<p>Mở file notepad_list.xml trong thư mục “res/layout”, dưới đây là một số điều bạn nên biết về file layout này:</p>
<ul>
<li>Tất      cả các file layout trong Android đều bắt đầu với dòng XML header:</li>
</ul>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="590" valign="top">&lt;?xml version=<em>&#8220;1.0&#8243;</em> encoding=<em>&#8220;utf-8&#8243;</em>?&gt;</td>
</tr>
</tbody>
</table>
<ul>
<li>Dòng      tiếp theo thường là một định nghĩa layout, trong ví dụ này là      LinearLayout.</li>
<li>Namespace      XML của Android luôn luôn được định nghĩa tại top level của component hay      layout trong XML để các tags “android:” có      thể được sử dụng thông qua phần còn lại của file.</li>
</ul>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="590" valign="top">xmlns:android=<em>&#8220;http://schemas.android.com/apk/res/android&#8221;</em></td>
</tr>
</tbody>
</table>
<h2>IV.Step 4</h2>
<p>Bây giờ, bạn cần tạo ra layout để nắm giữ list. Thêm đoạn mã sau vào bên trong phần tử LinearLayout như sau:</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="590" valign="top">&lt;?xml version=<em>&#8220;1.0&#8243;</em> encoding=<em>&#8220;utf-8&#8243;</em>?&gt;&nbsp;</p>
<p>&lt;LinearLayout xmlns:android=<em>&#8220;http://schemas.android.com/apk/res/android&#8221;</em></p>
<p>android:layout_width=<em>&#8220;wrap_content&#8221;</em></p>
<p>android:layout_height=<em>&#8220;wrap_content&#8221;</em>&gt;</p>
<p>&lt;ListView android:id=<em>&#8220;@android:id/list&#8221;</em></p>
<p>android:layout_width=<em>&#8220;wrap_content&#8221;</em></p>
<p>android:layout_height=<em>&#8220;wrap_content&#8221;</em>/&gt;</p>
<p>&lt;TextView android:id=<em>&#8220;@android:id/empty&#8221;</em></p>
<p>android:layout_width=<em>&#8220;wrap_content&#8221;</em></p>
<p>android:layout_height=<em>&#8220;wrap_content&#8221;</em></p>
<p>android:text=<em>&#8220;@string/no_notes&#8221;</em>/&gt;</p>
<p>&lt;/LinearLayout&gt;</td>
</tr>
</tbody>
</table>
<ul>
<li>Biểu      tượng @ trong id strings của các tag ListView và TextView      có nghĩa là XML parser nên parse và expand phần còn lại của id string và      sử dụng một ID resource.</li>
<li>ListView và TextView có thể được      xem như là hai view khác nhau, chỉ một trong số đó sẽ      được hiển thị tại một thời điểm. ListView sẽ được sử dụng khi      có các notes được hiển thị, trong khi TextView (trong đó có một giá trị mặc ​​định là &#8220;No Notes Yet!&#8221; được định nghĩa như là một string resource trong res/values/strings.xml) sẽ được hiển thị nếu không có bất      kỳ note nào để      hiển thị.<br />
Các ID list và empty được cung cấp cho bạn      bằng Android platform, vì vậy, chúng ta phải      prefix id với android: (ví dụ, @android:id/list).<br />
View với id      empty được sử dụng tự động      khi ListAdapter không có dữ liệu cho      ListView. Ngoài ra, bạn có thể thay view empty mặc định bằng cách sử dụng setEmptyView(View) trên ListView.</li>
<li>Nói rộng ra, lớp android.R là một tập hợp      các resource được định nghĩa trước cung cấp cho bạn      bởi platform, trong khi lớp R của project của      bạn là tập hợp các resource      project của      bạn đã được      định nghĩa. Các resource có trong lớp resource android.R có thể được sử dụng trong các file XML bằng cách      sử dụng prefix name space “android:” (như chúng ta thấy ở đây).</li>
</ul>
<h2>V.Step 5</h2>
<p>Để tạo ra danh sách các notes trong ListView, bạn cần định nghĩa một View cho một row:</p>
<p><strong> </strong></p>
<p><strong>B1.</strong>Tạo một layout resource mới “notes_row.xml” trong thư mục “res/layout”.</p>
<p><strong>B2.</strong>Thêm các nội dung sau đây file vừa tạo:</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="590" valign="top">&lt;?xml version=<em>&#8220;1.0&#8243;</em> encoding=<em>&#8220;utf-8&#8243;</em>?&gt;&nbsp;</p>
<p>&lt;TextView android:id=<em>&#8220;@+id/text1&#8243;</em></p>
<p>xmlns:android=<em>&#8220;http://schemas.android.com/apk/res/android&#8221;</em></p>
<p>android:layout_width=<em>&#8220;wrap_content&#8221;</em></p>
<p>android:layout_height=<em>&#8220;wrap_content&#8221;</em>/&gt;</td>
</tr>
</tbody>
</table>
<ul>
<li>Đây      là View được sử dụng để hiển thị mỗi notes title row – chỉ có một text      field bên trong nó.</li>
<li>Trong      trường hợp này, bạn tạo ra một id mới gọi là text1. Dấu “+” sau “@”      trong id string cho biết rằng id nên được tạo ra tự động như là một      resource nếu nó không tồn tại, vì vậy chúng ta định nghĩa nó để sử dụng.</li>
</ul>
<p><strong>B3.</strong>Lưu file.</p>
<p>Mở lớp R.java trong project của bạn, bạn sẽ thấy các định nghĩa mới cho notes_row và text1, có nghĩa là bây giờ chúng ta có thể truy cập vào chúng trong code.</p>
<h2>VI.Step 6</h2>
<ul>
<li>Tiếp      theo, mở lớp Notepadv1. Trong bước này,      bạn sẽ sửa đổi nó để trở thành một list adapter và hiển thị các notes,      đồng thời cho phép thêm note mới.</li>
<li>Notepadv1      kế thừa từ một lớp con của Activity, đó là      ListActivity, trong đó có chức      năng bổ sung cho phù hợp với loại      công việc mà bạn có thể muốn      làm việc trên một list,      ví dụ: hiển thị các list      item  trong các row lên màn hình, di chuyển qua      lại giữa các list item, và cho phép lựa      chọn trên chúng.</li>
<li>Trong      lớp này, có một biến mNoteNumber được sử      dụng để tạo ra các note title được đánh số (numbered). Đồng thời, chúng có      3 phương thức sẽ được override sau đây:
<ul>
<li>onCreate() được gọi khi activity được start, nó       được sử dụng để thiết lập (set up) các resource và state cho activity khi       nó đang chạy.</li>
<li>onCreateOptionsMenu() được sử dụng để populate       menu cho Activity. Menu sẽ được hiển thị khi user nhấn phím MENU trên       thiết bị, nó có một danh sách các option để user có thể chọn.</li>
<li>onOptionsItemSelected() được sử dụng để xử lý       các sự kiện phát sinh khi user chọn một item trong Menu.</li>
</ul>
</li>
</ul>
<h2>VII.Step 7</h2>
<ul>
<li>Thay      đổi lớp Notepadv1 kế thừa ListActivity thay vì Activity.</li>
</ul>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="590" valign="top"><strong>public</strong> <strong>class</strong> Notepadv1 <strong>extends</strong> ListActivity   {</td>
</tr>
</tbody>
</table>
<ul>
<li><strong>Lưu ý:</strong> Bạn sẽ phải import ListActivity vào Notepadv1      sử dụng Eclipse, nhấn tổ hợp phím ctrl-shift-O      trên Windows hay Linux, hay cmd-shift-O      trên Mac.</li>
</ul>
<h2>VIII.Step 8</h2>
<p>Cài đặt phương thức onCreate().</p>
<p>Ở đây bạn sẽ cài đặt title cho Activity (hiển thị ở top của màn hình), sử dụng layout “notepad_list” mà bạn đã tạo ra trước đó, thiết lập một thể hiện của NotesDbAdapter để truy cập dữ liệu note, và populate danh sách với các note title sẵn có:</p>
<ul>
<li><strong>B1.</strong>Trong phương thức onCreate(), gọi super.onCreate()      với tham số saveInstanceState.</li>
<li><strong>B2.</strong>Gọi setContentView()      và gán R.layout.notepad_list.</li>
<li><strong>B3.</strong>Tại top của lớp, tạo một biến      lớp private mới mDbHelper của lớp NotesDbAdapter.</li>
<li><strong>B4.</strong>Trở lại phương thức onCreate(), tạo ra một đối tượng mới NotesDbAdapter và gán nó cho trường mDbHelper.</li>
<li><strong>B5.</strong>Gọi phương thức open() trên mDbHelper      để mở (hay tạo mới) database.</li>
<li><strong>B6.</strong>Cuối cùng, tạo mới một phương      thức fillData() để nhận dữ liệu và      populate ListView sử dụng helper – chúng ta vẫn chưa định nghĩa phương      thức này.</li>
</ul>
<p>Phương thức onCreate() sẽ trông như sau:</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="590" valign="top">@Override&nbsp;</p>
<p><strong>public</strong> <strong>void</strong> onCreate(Bundle savedInstanceState) {</p>
<p><strong>super</strong>.onCreate(savedInstanceState);</p>
<p>setContentView(R.layout.<em>notepad_list</em>);</p>
<p>mDbHelper = <strong>new</strong> NotesDbAdapter(<strong>this</strong>);</p>
<p>mDbHelper.open();</p>
<p>fillData();</p>
<p>}</td>
</tr>
</tbody>
</table>
<p>Và đảm bảo rằng, bạn đã khai báo mDbHelper:</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="590" valign="top"><strong>private</strong> NotesDbAdapter mDbHelper;</td>
</tr>
</tbody>
</table>
<h2>IX.Step 9</h2>
<p>Cài đặt phương thức onCreateOptionsMenu().</p>
<p>Bây giờ, bạn sẽ tạo button “Add item” được truy cập bằng cách nhấn menu button trên thiết bị. Và chúng ta xác định rằng nó chiếm vị trí đầu tiên trong Menu.</p>
<ul>
<li><strong>B1.</strong>Trong resource “strings.xml” (trong thư mục “res/values”), và thêm một string mới được đặt      tên “menu_insert” với giá trị của nó là “Add Item”.</li>
</ul>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="590" valign="top">&lt;string   name=<em>&#8220;menu_insert&#8221;</em>&gt;Add Item&lt;/string&gt;</td>
</tr>
</tbody>
</table>
<ul>
<li>Sau      đó lưu file và trở về Notepadv1.</li>
<li><strong>B2.</strong>Tạo một hằng menu position tại      top của lớp:</li>
</ul>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="590" valign="top"><strong>public</strong> <strong>static</strong> <strong>final</strong> <strong>int</strong> <em>INSERT_ID</em> = Menu.<em>FIRST</em>;</td>
</tr>
</tbody>
</table>
<ul>
<li><strong>B3.</strong>Trong phương thức onCreateOptionsMenu(), khai báo một biến cục bộ result kiểu boolean      và gán cho super.onCreateOptionsMenu().</li>
<li><strong>B4.</strong>Sau đó, thêm menu item với      phương thức add().</li>
</ul>
<ul>
<li>Bây      giờ phương thức onCreateOptionsMenu()      trông như sau:</li>
</ul>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="590" valign="top">@Override&nbsp;</p>
<p><strong>public</strong> <strong>boolean</strong> onCreateOptionsMenu(Menu menu) {</p>
<p><strong>boolean</strong> result = <strong>super</strong>.onCreateOptionsMenu(menu);</p>
<p>menu.add(0, <em>INSERT_ID</em>, 0, R.string.<em>menu_insert</em>);</p>
<p><strong>return</strong> result;</p>
<p>}</td>
</tr>
</tbody>
</table>
<ul>
<li>Các      đối số được gán vào trong phương thức add()      cho biết: một group identifier, một unique ID, thứ tự của item và resource      của string để sử dụng cho item.</li>
</ul>
<h2>X.Step 10</h2>
<p>Cài đặt phương thức onOptionsItemSelected().</p>
<p>Trong phần này, chúng ta sẽ xử lý menu item “Add Note”. Khi item này trên Menu được chọn, phương thức onOptionsItemSelected() sẽ được gọi với item.getId() thiết lập cho INSERT_ID (hằng mà bạn sử dụng để identify menu item).</p>
<ul>
<li><strong>B1.</strong>Gọi super.onOptionsItemSelected()      vào cuối phương thức này.</li>
<li><strong>B2.</strong>Viết một biểu thức “switch” dựa vào item.getId().</li>
</ul>
<p>Phương thức onOptionsItemSelected() trông như sau:</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="590" valign="top">@Override&nbsp;</p>
<p><strong>public</strong> <strong>boolean</strong> onOptionsItemSelected(MenuItem item) {</p>
<p><strong>switch</strong> (item.getItemId()) {</p>
<p><strong>case</strong> <em>INSERT_ID</em>:</p>
<p>createNote();</p>
<p><strong>return</strong> <strong>true</strong>;</p>
<p>}</p>
<p><strong>return</strong> <strong>super</strong>.onOptionsItemSelected(item);</p>
<p>}</td>
</tr>
</tbody>
</table>
<h2>XI.Step 11</h2>
<p>Cài đặt phương thức createNote().</p>
<p>Trong phương thức này, bạn đơn giãn chỉ tạo một note mới với title được gán dựa trên một counter (ví dụ, “Note 1”, “Note 2”…) với một body trống.</p>
<ul>
<li><strong>B1.</strong>Xây dựng name với “Note” và      counter được định nghĩa trong lớp này:</li>
</ul>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="590" valign="top">String noteName = &#8220;Note   &#8221; + mNoteNumber++;</td>
</tr>
</tbody>
</table>
<ul>
<li><strong>B2.</strong>Gọi mDbHelper.createNote()      sử dụng noteName làm title và “” làm body .</li>
<li><strong>B3.</strong>Gọi phương thức fillData() để populate danh sách các notes –      phương thức này sẽ được tạo trong bước tiếp theo.</li>
</ul>
<ul>
<li>Phương      thức createNote() trông như sau:</li>
</ul>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="590" valign="top"><strong>private</strong> <strong>void</strong> createNote()   {&nbsp;</p>
<p>String noteName = &#8220;Note   &#8221; + mNoteNumber++;</p>
<p>mDbHelper.createNote(noteName,   &#8220;&#8221;);</p>
<p>fillData();</p>
<p>}</td>
</tr>
</tbody>
</table>
<h2>XII.Step 12</h2>
<ul>
<li>Định      nghĩa và cài đặt phương thức fillData().</li>
<li>Phương      thức này sử dụng SimpleCursorAdapter và      một Cursor để bind nó vào các field được      cung cấp trong layout. Các field này định nghĩa các phần tử row của list      (trong ví dụ này, field text1 trong layout      “notes_row.xml”).</li>
<li>Để làm điều này bạn phải cung      cấp một mapping từ field title trong Cursor trả về đến text1, mà được      thực hiện bằng cách định nghĩa hai mảng: đầu      tiên là một mảng string với danh sách các column cho map (trong ví dụ này là &#8220;title&#8221;, từ constant NotesDbAdapter.KEY_TITLE) và, thứ hai là một mảng      int có chứa các      tham chiếu đến các view để bạn bind dữ liệu vào (R.id.text1).</li>
</ul>
<table border="1" cellspacing="0" cellpadding="0" width="643">
<tbody>
<tr>
<td width="643" valign="top"><strong>private</strong> <strong>void</strong> fillData() {&nbsp;</p>
<p>// Get all of the notes from the   database and create the item list</p>
<p>Cursor c = mDbHelper.fetchAllNotes();</p>
<p>startManagingCursor(c);</p>
<p>String[] from = <strong>new</strong> String[] {   NotesDbAdapter.<em>KEY_TITLE</em> };</p>
<p><strong>int</strong>[] to = <strong>new</strong> <strong>int</strong>[] { R.id.<em>text1</em> };</p>
<p>// Now create an array adapter and   set it to display using our row</p>
<p>SimpleCursorAdapter notes = <strong>new</strong> SimpleCursorAdapter(<strong>this</strong>,</p>
<p>R.layout.<em>notes_row</em>, c, from,   to);</p>
<p>setListAdapter(notes);</p>
<p>}</td>
</tr>
</tbody>
</table>
<p>Sau đây là những gì mà chúng ta đã thực hiện:</p>
<ul>
<li><strong>B1.</strong>Sau khi nhận được Cursor từ mDbHelper.fetchAllNotes(), chúng ta sử dụng      phương thức startManagingCursor() của      Activity để cho phép Android quan tâm đến lifecycle của Cursor thay vì      chúng ta lo lắng về điều đó (chúng ta sẽ thảo luận vấn đề này trong bài tập      3, nhưng bây giờ chỉ biết rằng điều này cho phép Android làm một số công      việc quản lý resource cho bạn).</li>
<li><strong>B2.</strong>Sau đó chúng ta tạo ra một mảng string, trong đó khai báo các column      mà chúng ta muốn (trong ví dụ này, chỉ có title), và một mảng int      định nghĩa các View mà chúng ta      muốn bind các column.</li>
<li><strong>B3.</strong>Bước tiếp theo là khởi tạo SimpleCursorAdapter. Giống như nhiều lớp trong      Android, SimpleCursorAdapter cần một      Context để thực hiện các công việc của nó, vì vậy chúng ta gán “this” cho      context (các lớp con của Activity thực thi Context). Chúng ta gán View “notes_row” đã tạo ra trước đó để làm chỗ chứa      (receptable) cho dữ liệu, Cursor mà chúng ta vừa tạo ra và các mảng.</li>
</ul>
<p>Trong tương lai, hãy nhớ rằng việc mapping từ các column và các resource được thực hiện bằng cách sử dụng thứ tự của hai mảng một cách tương ứng. Nếu bạn đã có nhiều column để bind, và nhiều View để bind chúng vào, bạn sẽ xác định chúng theo thứ tự, ví dụ bạn có thể sử dụng {NotesDbAdapter.KEY_TITLE, NotesDbAdapter.KEY_BODY} và {R.id.text1, R. id.text2} để bind hai field vào row (và cũng cần phải định nghĩa text2 trong notes_row.xml, cho body text). Đây là cách mà bạn có thể bind các field vào một row đơn (và có được một custom row layout).</p>
<h2>XIII.Step 13</h2>
<ul>
<li>Chạy      ứng dụng.</li>
</ul>
<p>Link tham khảo: <a href="http://developer.android.com/resources/tutorials/notepad/notepad-ex1.html">http://developer.android.com/resources/tutorials/notepad/notepad-ex1.html</a>.</p>
<br />Filed under: <a href='http://mobilesprogramming.wordpress.com/category/android/'>Android</a>, <a href='http://mobilesprogramming.wordpress.com/category/android/android-tutorial/'>Android Tutorial</a> Tagged: <a href='http://mobilesprogramming.wordpress.com/tag/android_basic/'>android_basic</a>, <a href='http://mobilesprogramming.wordpress.com/tag/android_tutorial/'>android_tutorial</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mobilesprogramming.wordpress.com/780/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mobilesprogramming.wordpress.com/780/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mobilesprogramming.wordpress.com/780/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mobilesprogramming.wordpress.com/780/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/mobilesprogramming.wordpress.com/780/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/mobilesprogramming.wordpress.com/780/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/mobilesprogramming.wordpress.com/780/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/mobilesprogramming.wordpress.com/780/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mobilesprogramming.wordpress.com/780/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mobilesprogramming.wordpress.com/780/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mobilesprogramming.wordpress.com/780/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mobilesprogramming.wordpress.com/780/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mobilesprogramming.wordpress.com/780/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mobilesprogramming.wordpress.com/780/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mobilesprogramming.wordpress.com&amp;blog=11410337&amp;post=780&amp;subd=mobilesprogramming&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mobilesprogramming.wordpress.com/2011/03/16/notepad-example-ph%e1%ba%a7n-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/992f5fba26e8af9ebb4a25d922f208c6?s=96&#38;d=&#38;r=G" medium="image">
			<media:title type="html">mobilesprogramming</media:title>
		</media:content>
	</item>
		<item>
		<title>Cơ Bản Android &#8211; Tích Hợp Android Vào Eclipse &#8211; Phần 1</title>
		<link>http://mobilesprogramming.wordpress.com/2011/03/15/c%c6%a1-b%e1%ba%a3n-android-tich-h%e1%bb%a3p-android-vao-eclipse-ph%e1%ba%a7n-1/</link>
		<comments>http://mobilesprogramming.wordpress.com/2011/03/15/c%c6%a1-b%e1%ba%a3n-android-tich-h%e1%bb%a3p-android-vao-eclipse-ph%e1%ba%a7n-1/#comments</comments>
		<pubDate>Tue, 15 Mar 2011 03:16:53 +0000</pubDate>
		<dc:creator>mobilesprogramming</dc:creator>
				<category><![CDATA[android_basic]]></category>
		<category><![CDATA[android_tutorial]]></category>

		<guid isPermaLink="false">http://mobilesprogramming.wordpress.com/?p=767</guid>
		<description><![CDATA[I.Hướng Dẫn Cài Đặt Android Với Eclipse 1.Download Android SDK Android SDK thực chất là tập hợp các công cụ và thư viện để phát triển các ứng dụng trên nền tảng hệ điều hành Android. B1: Vào trang http://developer.android.com/sdk/index.html để tải Android SDK Starter. Tùy thuộc vào hệ điều hành mà bạn chọn bản [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mobilesprogramming.wordpress.com&amp;blog=11410337&amp;post=767&amp;subd=mobilesprogramming&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<h2>I.Hướng Dẫn Cài Đặt Android Với Eclipse</h2>
<h3>1.Download Android SDK</h3>
<p>Android SDK thực chất là tập hợp các công cụ và thư viện để phát triển các ứng dụng trên nền tảng hệ điều hành Android.</p>
<p>B1: Vào trang <a href="http://developer.android.com/sdk/index.html" target="_blank">http://developer.android.com/sdk/index.html</a> để tải Android SDK Starter. Tùy thuộc vào hệ điều hành mà bạn chọn bản Mac, Linux hay Window. Ở đây mình chọn tải bản cho Window.</p>
<p><a href="http://mobilesprogramming.files.wordpress.com/2011/03/untitled.png"><img class="aligncenter size-medium wp-image-768" title="Untitled" src="http://mobilesprogramming.files.wordpress.com/2011/03/untitled.png?w=300&#038;h=78" alt="" width="300" height="78" /></a></p>
<p>B2: Giải nén file zip bạn vừa tải về. Chạy SDK Setup.exe. Bạn có thể gặp thông báo lỗi Fetching <a href="https://dl-sl/" target="_blank">https://dl-sl</a>&#8230; Failed to fetch&#8230; Close thông báo này lại. Tiếp theo cửa sổ Choose Packages to Install xuất hiện. Nếu cửa sổ này trống rỗng -&gt; Cancel.</p>
<p>-&gt; Quay về cửa sổ Android SDK and AVD manager -&gt; Chọn Setting, đánh dấu vào ô Force <a href="https://./" target="_blank">https://.</a>..</p>
<p>-&gt; Chọn Available Packages.<span id="more-767"></span></p>
<p><a href="http://mobilesprogramming.files.wordpress.com/2011/03/bai1_img2.png"><img class="aligncenter size-medium wp-image-769" title="Bai1_img2" src="http://mobilesprogramming.files.wordpress.com/2011/03/bai1_img2.png?w=300&#038;h=148" alt="" width="300" height="148" /></a></p>
<p>B3: Đánh dấu các Packages bạn muốn tải: Documents chính là phần Javadoc mô tả hoạt động của các phương thức và các lớp (phần này chắc chắn không thể thiếu rồi), Sample là các đoạn code mẫu, SDK Platform ứng với các phiên bản hệ điều hành (2.2 &#8211; API level 8, 2.1 &#8211; API level 7,&#8230;), và Google API để phát triển các phần mềm liên quan đến dịch vụ của Google (như Google Map nếu bạn muốn lập trình liên quan đến GPS).<br />
Các bạn có thể tải hết nếu thích, còn muốn tối ưu thì có thể đánh dấu như mình (lưu ý USB drivers chỉ dành cho người sử dụng Windows và muốn phát triển ứng dụng test bằng điện thoại thật).</p>
<p>-&gt;    Install Selected</p>
<p>-&gt;   Install</p>
<p>-&gt;    Cửa sổ Install hiện ra</p>
<p>-&gt;    Ngồi chờ (&gt;_&lt;)</p>
<p><a href="http://mobilesprogramming.files.wordpress.com/2011/03/bai1_img3.png"><img class="aligncenter size-medium wp-image-770" title="Bai1_img3" src="http://mobilesprogramming.files.wordpress.com/2011/03/bai1_img3.png?w=300&#038;h=190" alt="" width="300" height="190" /></a></p>
<h3>2.Tích hợp Android SDK vào Eclipse</h3>
<p>B1: Tải Eclipse nếu bạn chưa có. Mọi người có thể phân vân không biết tải bản nào cho phù hợp, nhưng theo ý kiến của mình thì có thể dùng 1 trong 2 bản sau: Eclipse for Java Developers, hoặc Eclipse for Java and Report Developers (mình dùng bản sau).</p>
<p>B2: Khởi chạy Eclipse, vào Help -&gt; Install new softwares.<br />
Chọn Add, gõ vào ô Name tên bạn muốn và Location gõ vào địa chỉ để tải về ADT.</p>
<p>HTML code:</p>
<p>&nbsp;</p>
<div>
<pre>https://dl-ssl.google.com/android/eclipse/</pre>
</div>
<p>&nbsp;</p>
<p>Hoặc:</p>
<p>&nbsp;</p>
<div>
<pre>http://dl-ssl.google.com/android/eclipse/</pre>
</div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>Nếu https không hoạt động. Ngoài ra bạn cũng có thể tải thẳng ADT về máy theo link <a href="http://dl.google.com/android/ADT-0.9.7.zip" target="_blank">http://dl.google.com/android/ADT-0.9.7.zip</a> (bản mới nhất 0.9.7 ứng với Android 2.2), chọn Archive và browse tới file này (lưu ý không giải nén)<br />
-&gt; OK<br />
-&gt; Check vào phần dưới ô Name (sẽ hiện ra dòng Developer Tools).</p>
<p><a href="http://mobilesprogramming.files.wordpress.com/2011/03/bai1_img4.png"><img class="aligncenter size-medium wp-image-771" title="Bai1_img4" src="http://mobilesprogramming.files.wordpress.com/2011/03/bai1_img4.png?w=300&#038;h=261" alt="" width="300" height="261" /></a></p>
<p>B3: Next, next, Accept, next,&#8230;Finish (như Install mọi chương trình bình thường).</p>
<p>B4: Eclipse -&gt; Windows -&gt; Preferences -&gt; Android<br />
Nhấn nút Browse và chỉnh đường dẫn tới thư mục của Android SDK bạn tải lúc trước.<br />
-&gt; Apply<br />
-&gt; OK</p>
<p><a href="http://mobilesprogramming.files.wordpress.com/2011/03/bai1_img5.png"><img class="aligncenter size-medium wp-image-772" title="Bai1_img5" src="http://mobilesprogramming.files.wordpress.com/2011/03/bai1_img5.png?w=300&#038;h=255" alt="" width="300" height="255" /></a></p>
<h3>3.Android Virtual Device(Emulator)</h3>
<p>AVD là máy ảo cho developer phát triển ứng dụng. Để tạo 1 AVD bạn vào Windows -&gt; Android SDK and AVD Manager -&gt; Virtual Devices chọn New.<br />
-&gt; Cửa sổ Create new AVD hiện ra, bạn điền thông tin cho AVD bạn muốn:</p>
<p>&nbsp;</p>
<p><strong>Name</strong>: Tùy ý (nhưng chỉ được sử dụng các ký tự &#8220;a-z&#8221;, &#8220;A-Z&#8221;, &#8220;.-_&#8221;, nghĩa là cả khoảng trắng cũng ko đc).<br />
<strong>Target</strong>: Chọn phiên bản hệ điều hành bạn muốn (thường mình tạo một Android 1.6 và một Android 2.2 để test).</p>
<p><strong>SD Card</strong>: gõ vào Size SD card ảo cho AVD, hoặc chỉnh tới file đã có sẵn. Nhiều AVD có thể dùng chung 1 Sdcard (chỉ cần tạo lần đầu, các lần sau chỉnh đường dẫn tới file đó).</p>
<p><strong>Skin</strong>: có thể để Default (HVGA) hoặc chọn kích cỡ màn hình bạn muốn. Chỉ cần quan tâm tới 3 option: HVGA (phân giải 320-480 như G1, G2, i5700&#8230;), QVGA (240-320 như HTC Wildfire&#8230;), WVGA854 (480-854 như Milestone, NexusOne&#8230;)<br />
-&gt; Create AVD.</p>
<p><a href="http://mobilesprogramming.files.wordpress.com/2011/03/bai1_img6.png"><img class="aligncenter size-medium wp-image-773" title="Bai1_img6" src="http://mobilesprogramming.files.wordpress.com/2011/03/bai1_img6.png?w=216&#038;h=300" alt="" width="216" height="300" /></a></p>
<h2>II.Một Số Chức Năng Cần Thiết Khi Lập Trình Android Với Eclipse</h2>
<p>Những điều mình nêu ra dưới đây đều là cơ bản, có thể các pro đã biết hết rồi, nhưng như mình đã nói, bài này là dành cho newbie với hi vọng gia tăng kiến thức cơ bản cùng giảm thời gian tìm kiếm cho các bạn.</p>
<h3>1.Debug cho ứng dụng Android</h3>
<p>Nhiều người chuyển từ J2SE hoặc J2ME sang Android sẽ ngạc nhiên vì câu lệnh debug kinh điển <strong>System.out.println()</strong> không còn in ra trên cửa sổ Console nữa. Google đã thay thế nó bằng Logcat, một cửa sổ ghi lại toàn bộ hoạt động của hệ điều hành. Để mở Logcat, trước tiên các bạn chọn Window -&gt; Open Perspective -&gt; Debug. Nếu ko thấy option Debug thì chọn Other và tìm Debug trong cửa sổ mới hiện ra. Sau đó chọn tab Debug mới xuất hiện ở góc trên bên phải của Eclipse (xem hình). Theo kinh nghiệm của mình thì tốt nhất là Maximize Logcat ra luôn cho dễ quan sát.</p>
<p>Cảm nhận ngày xưa khi mới sử dụng Logcat là rối và khó dùng. Nhưng càng về sau mình càng quen và thấy nó tiện hơn Console nhiều, vì Console chỉ đưa ra thông báo do chúng ta gọi, còn Logcat thì đưa cả luôn những thông báo của hệ điều hành, giúp chúng ta nắm được hệ điều hành đang làm gì, gọi đến cái gì, khởi chạy những gì&#8230;</p>
<p><a href="http://mobilesprogramming.files.wordpress.com/2011/03/bai1_img7.png"><img class="aligncenter size-medium wp-image-774" title="Bai1_img7" src="http://mobilesprogramming.files.wordpress.com/2011/03/bai1_img7.png?w=300&#038;h=257" alt="" width="300" height="257" /></a></p>
<h3>2.File Explore Của Android</h3>
<p>File Explorer là một chức năng hữu ích Google đưa vào giúp chúng ta quản lý file trong sd card và cả file system data (chỉ quản lý được của emulator, không thể truy nhập system data của thiết bị thật). FE giúp bạn dễ dàng đưa file vào / lấy file ra trong sdcard ảo của emulator, xóa cơ sở dữ liệu của chương trình để khởi tạo lại (only emulator)&#8230;</p>
<p>Mở FE bằng cách vào Window -&gt; Show View -&gt; Others -&gt; Android -&gt; File Explorer. Mình để FE trong cửa sổ Debug cho tiện quản lý.</p>
<p><a href="http://mobilesprogramming.files.wordpress.com/2011/03/bai1_img8.png"><img class="aligncenter size-medium wp-image-775" title="Bai1_img8" src="http://mobilesprogramming.files.wordpress.com/2011/03/bai1_img8.png?w=300&#038;h=257" alt="" width="300" height="257" /></a></p>
<h3>3.Device của Android</h3>
<p>Device cũng là một chức năng hữu ích nữa trong Android giúp bạn quản lý thiết bị ảo cũng như thật của mình. Mở Device bằng cách vào Window -&gt; Show View -&gt; Device hoặc vào Window -&gt; Show View -&gt; Others -&gt; Android -&gt; Device.</p>
<p>Chức năng mình thường sử dụng nhất của device là Screen Capture, cực kỳ tiện để lấy ảnh minh họa làm thuyết trình hoặc giới thiệu trên Google Market.</p>
<p><a href="http://mobilesprogramming.files.wordpress.com/2011/03/bai1_img9.png"><img class="aligncenter size-medium wp-image-776" title="Bai1_img9" src="http://mobilesprogramming.files.wordpress.com/2011/03/bai1_img9.png?w=300&#038;h=258" alt="" width="300" height="258" /></a></p>
<h2>III.Một Số Thủ Thuật Trong Android Và Eclipse</h2>
<h3>1.Hiển thị tiếng Việt</h3>
<p>Window -&gt; Preferences -&gt; General -&gt; Workspace.</p>
<p>Trong Workspace phần Text File Encoding chọn Other -&gt; UTF-8.</p>
<h3>2.Tự động sổ code</h3>
<p>Tổ hợp phím kinh điển Ctrl + Space (điều kỳ lạ là khá nhiều người không biết).</p>
<h3>3.Comment</h3>
<p>Ctrl + &#8220;/&#8221;: tự động thêm cụm &#8220;//&#8221; vào đầu dòng (ko tiện lắm).<br />
Ctrl + Shift + &#8220;/&#8221;: tự động thêm &#8220;/* */&#8221; vào cụm được bôi đen.<br />
Ctrl + Shift + &#8220;\&#8221;: tự động bỏ &#8220;/* */&#8221; vào cụm được bôi đen.</p>
<h3>4.Override</h3>
<p>Đôi lúc bạn muốn Override phương thức của một lớp có sẵn, ko lẽ chúng ta sẽ đi tìm tên phương thức trên mạng và gõ đúng lại như thế? Nhiều bạn đã gặp lỗi khi định viết lại phương thức này và debug mãi ko ra (vì nó ko phải là lỗi).<br />
Mã:</p>
<div>
<pre>@Override

        public boolean onCreateOptionsMenu(Menu menu) {

               

        }</pre>
</div>
<p>đơn giản vì gõ thiếu chữ s.<br />
Eclipse cung cấp phương tiện giúp ta ghi đè phương thức của lớp cha với Source -&gt; Override/Implement Method, nhưng cực kỳ nhiều người không biết.</p>
<p>Tham khảo từ http://diendan.vietandroid.com/ca-c-ba-i-ha-c-ca-ka-m-ma-ngua-n/1192-hae-ng-da-n-la-p-tra-nh-cae-ba-n-va-i-android-ba-i-0-a.html.</p>
<p>&nbsp;</p>
<br /> Tagged: <a href='http://mobilesprogramming.wordpress.com/tag/android_basic/'>android_basic</a>, <a href='http://mobilesprogramming.wordpress.com/tag/android_tutorial/'>android_tutorial</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mobilesprogramming.wordpress.com/767/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mobilesprogramming.wordpress.com/767/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mobilesprogramming.wordpress.com/767/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mobilesprogramming.wordpress.com/767/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/mobilesprogramming.wordpress.com/767/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/mobilesprogramming.wordpress.com/767/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/mobilesprogramming.wordpress.com/767/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/mobilesprogramming.wordpress.com/767/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mobilesprogramming.wordpress.com/767/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mobilesprogramming.wordpress.com/767/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mobilesprogramming.wordpress.com/767/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mobilesprogramming.wordpress.com/767/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mobilesprogramming.wordpress.com/767/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mobilesprogramming.wordpress.com/767/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mobilesprogramming.wordpress.com&amp;blog=11410337&amp;post=767&amp;subd=mobilesprogramming&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mobilesprogramming.wordpress.com/2011/03/15/c%c6%a1-b%e1%ba%a3n-android-tich-h%e1%bb%a3p-android-vao-eclipse-ph%e1%ba%a7n-1/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/992f5fba26e8af9ebb4a25d922f208c6?s=96&#38;d=&#38;r=G" medium="image">
			<media:title type="html">mobilesprogramming</media:title>
		</media:content>

		<media:content url="http://mobilesprogramming.files.wordpress.com/2011/03/untitled.png?w=300" medium="image">
			<media:title type="html">Untitled</media:title>
		</media:content>

		<media:content url="http://mobilesprogramming.files.wordpress.com/2011/03/bai1_img2.png?w=300" medium="image">
			<media:title type="html">Bai1_img2</media:title>
		</media:content>

		<media:content url="http://mobilesprogramming.files.wordpress.com/2011/03/bai1_img3.png?w=300" medium="image">
			<media:title type="html">Bai1_img3</media:title>
		</media:content>

		<media:content url="http://mobilesprogramming.files.wordpress.com/2011/03/bai1_img4.png?w=300" medium="image">
			<media:title type="html">Bai1_img4</media:title>
		</media:content>

		<media:content url="http://mobilesprogramming.files.wordpress.com/2011/03/bai1_img5.png?w=300" medium="image">
			<media:title type="html">Bai1_img5</media:title>
		</media:content>

		<media:content url="http://mobilesprogramming.files.wordpress.com/2011/03/bai1_img6.png?w=216" medium="image">
			<media:title type="html">Bai1_img6</media:title>
		</media:content>

		<media:content url="http://mobilesprogramming.files.wordpress.com/2011/03/bai1_img7.png?w=300" medium="image">
			<media:title type="html">Bai1_img7</media:title>
		</media:content>

		<media:content url="http://mobilesprogramming.files.wordpress.com/2011/03/bai1_img8.png?w=300" medium="image">
			<media:title type="html">Bai1_img8</media:title>
		</media:content>

		<media:content url="http://mobilesprogramming.files.wordpress.com/2011/03/bai1_img9.png?w=300" medium="image">
			<media:title type="html">Bai1_img9</media:title>
		</media:content>
	</item>
		<item>
		<title>Lập Trình Với Blackberry – Phần 3</title>
		<link>http://mobilesprogramming.wordpress.com/2010/12/21/l%e1%ba%adp-trinh-v%e1%bb%9bi-blackberry-%e2%80%93-ph%e1%ba%a7n-3/</link>
		<comments>http://mobilesprogramming.wordpress.com/2010/12/21/l%e1%ba%adp-trinh-v%e1%bb%9bi-blackberry-%e2%80%93-ph%e1%ba%a7n-3/#comments</comments>
		<pubDate>Tue, 21 Dec 2010 08:26:23 +0000</pubDate>
		<dc:creator>mobilesprogramming</dc:creator>
				<category><![CDATA[BB Tutorial]]></category>
		<category><![CDATA[Blackberry]]></category>
		<category><![CDATA[basic-BB]]></category>

		<guid isPermaLink="false">http://mobilesprogramming.wordpress.com/?p=754</guid>
		<description><![CDATA[Bài 2:  Tạo Form Login Sử Dụng Blackberry        Component (Tiếp theo) II.       Xử Lý Tương Tác Người Dùng Trong ví dụ trên, bạn có thể di chuyển focus giữa các Field, nhập dữ liệu cho TextField, thay đổi giá trị cho ObjectChoiceField, hay đánh dấu chọn cho CheckBox…Tuy nhiên, khi click vào các Button thì [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mobilesprogramming.wordpress.com&amp;blog=11410337&amp;post=754&amp;subd=mobilesprogramming&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<h1>Bài 2:  Tạo Form Login Sử Dụng Blackberry        Component (Tiếp theo)</h1>
<h2>II.       Xử Lý Tương Tác Người Dùng</h2>
<p>Trong ví dụ trên, bạn có thể di chuyển focus giữa các Field, nhập dữ liệu cho TextField, thay đổi giá trị cho ObjectChoiceField, hay đánh dấu chọn cho CheckBox…Tuy nhiên, khi click vào các Button thì vẫn chưa có tương tác gì. Trong mục này, chúng ta sẽ xử lý tiếp các sự kiện trên Button.</p>
<h3>1.     Xử lý các sự kiện UI</h3>
<p>Blackberry API sử dụng observer pattern để gửi đi (dispatch) các sự kiện. Tất cả các Field có thể đăng ký một listener cho chúng, và listener này được thông báo khi có sự thay đổi sự kiện được phát sinh.</p>
<ul>
<li>Đối với ButtonField, một event được phát sinh khi button được click bởi trackball hay touch (màn hình touch), hay phím Enter được nhấn khi button được highlight.</li>
<li>Đối với CheckboxField, một event được phát sinh khi checkbox được check hay uncheck.</li>
<li>Đối với ChoiceField, một event được phát sinh khi người dùng lựa chọn một choice khác.</li>
</ul>
<p>Để đăng khi listener cho Field, sử dụng phương thức Field.setChangeListener().</p>
<p><strong>Lưu ý</strong> Blackberry cung cấp một mô hình sự kiện unicast, đó là chỉ có nhiều nhất một change listener cho một Field. Nếu sử dụng Field.setChangeListener(), tức là bạn đã thay thế cho listener đã tồn tại trước đó trong Field, ngăn cản nó nhận các sự kiện.</p>
<p>Một listener phải thực thi một giao diện FieldChangeListener. Trong ví dụ này, chúng ta sẽ để UiFunMainScreen thực thi giao diện net.rim.device.api.ui.FieldChangeListener, trong phương thức này có một phương thức fieldChanged() để xử lý các sự kiện phát sinh trên các Field, cụ thể như sau:<span id="more-754"></span></p>
<p><em>public class UiFunMainScreen extends MainScreen implements FieldChangeListener { </em></p>
<p><em>public void fieldChanged(Field field, int context) { </em></p>
<p><em>}</em></p>
<h3>2.     Xử lý Clear Button</h3>
<p>Đầu tiên, chúng ta sẽ đăng ký sự kiện cho Clear Button như sau:</p>
<p><em>clearButton.setChangeListener(this);</em></p>
<p>Sau đó, trong phương thức fieldChanged(), chúng ta xử lý xự kiện cho Clear button; trong ví dụ này mỗi lần người dùng nhấn vào Clear button, chúng ta sẽ xuất một hộp hội thoại thông báo người dùng đã nhấn vào Clear buttton:</p>
<p><em>public void fieldChanged(Field field, int context) { </em></p>
<p><em> if (field == clearButton) { </em></p>
<p><em> Dialog.inform(&#8220;Clear Button Pressed!&#8221;); </em></p>
<p><em> } </em></p>
<p><em>}</em></p>
<p>Đến lúc này, nếu bạn chạy ứng dụng và nhấn vào Clear, ứng dụng sẽ hiển thị như sau:</p>
<p><a href="http://mobilesprogramming.files.wordpress.com/2010/12/bai26.png"><img class="aligncenter size-medium wp-image-755" title="bai26" src="http://mobilesprogramming.files.wordpress.com/2010/12/bai26.png?w=220&#038;h=300" alt="" width="220" height="300" /></a></p>
<p>Nếu bạn muốn sử dụng Clear button để xóa chuỗi text trên usename và password, bạn xây dựng một phương thức clearTextField() như sau:</p>
<p>&nbsp;</p>
<p><em>private void clearTextFields() { </em></p>
<p><em> usernameField.setText(&#8220;&#8221;); </em></p>
<p><em> passwordField.setText(&#8220;&#8221;); </em></p>
<p><em>}</p>
<p></em></p>
<p>Sau đó, trong phương thức fieldChanged(), gọi phương thức clearTextField() như sau:</p>
<p>&nbsp;</p>
<p>public void fieldChanged(Field field, int context) {</p>
<p>if (field == clearButton) {</p>
<p>clearTextFields();</p>
<p>}</p>
<p>}</p>
<p><strong> </strong></p>
<h3>3.     Xử lý Login button</h3>
<p>Trong Login button , chúng ta kiểm tra nếu usename và password trống thì sẽ hiển thị một hộp thoại cảnh báo; ngược lại nếu chúng có dữ liệu thì chúng ta sẽ kích hoạt một màn hình mới để thông báo người dùng đã đăng nhập thành công.</p>
<h4>3.1.                        Định nghĩa một màn hình mới</h4>
<p>Trong mục này, chúng ta tạo ra một màn hình mới có tên LoginSuccessScreen, trong lớp này sẽ có 3 LabelField, label đầu tiên thông báo đã login thành công, 2 label còn lại hiển thị usename và domain.</p>
<p>package blog.mobilesprogramming.uifun;</p>
<p><em>import net.rim.device.api.ui.component.LabelField; </em></p>
<p><em>import net.rim.device.api.ui.container.MainScreen;</em></p>
<p><em> </em></p>
<p><em>public class LoginSuccessScreen extends MainScreen { </em></p>
<p><em> public LoginSuccessScreen(String username, String domain) { </em></p>
<p><em> add(new LabelField(&#8220;Logged in!&#8221;)); </em></p>
<p><em> add(new LabelField(&#8220;Username: &#8221; + username)); </em></p>
<p><em> add(new LabelField(&#8220;Domain: &#8221; + domain)); </em></p>
<p><em> } </em></p>
<p><em>}</em></p>
<h4>3.2.                        Xây dựng phương thức login()</h4>
<p>Chúng ta xây dựng phương thức login() để kiểm tra xem usename và password có trống hay không, nếu trống thì hiển thị một hộp hội thoại để cảnh báo; ngược lại thì hiển thị màn hình LoginSuccessScreen.<br />
<em>private void login() { </em></p>
<p><em> if (usernameField.getTextLength() == 0 || passwordField.getTextLength() == 0) { </em></p>
<p><em> Dialog.alert(&#8220;You must enter a username and password&#8221;); </em></p>
<p><em> } </em></p>
<p><em> else { </em></p>
<p><em> String username = usernameField.getText(); </em></p>
<p><em> String selectedDomain = </em></p>
<p><em> (String)domainField.getChoice(domainField.getSelectedIndex()); </em></p>
<p><em> LoginSuccessScreen loginSuccessScreen = </em></p>
<p><em> new LoginSuccessScreen(username, selectedDomain); </em></p>
<p><em> UiApplication.getUiApplication().pushScreen(loginSuccessScreen); </em></p>
<p><em> } </em></p>
<p><em> }</em></p>
<p>Tiếp theo,trong phương thức fieldChanged() của lớp UiFunMainScreen, chúng ta gọi phương thức login():</p>
<p>public void fieldChanged(Field field, int context) {</p>
<p>if (field == clearButton) {</p>
<p>clearTextFields();</p>
<p>}</p>
<p>else if (field == loginButton) {</p>
<p>login();</p>
<p>}</p>
<p>}</p>
<p><strong>Lưu ý</strong> Bạn phải đăng ký sự kiện cho Login button bằng cách gọi phương thức</p>
<p>loginButton.setChangeListener(this);<br />
Bây giờ, nếu bạn chạy ứng dụng và nhấn vào Login button thì sẽ có giao diện như sau:<br />
<a href="http://mobilesprogramming.files.wordpress.com/2010/12/bai27.png"><img class="aligncenter size-medium wp-image-756" title="bai27" src="http://mobilesprogramming.files.wordpress.com/2010/12/bai27.png?w=231&#038;h=300" alt="" width="231" height="300" /></a></p>
<p><a href="http://www.megaupload.com/?d=J9DBIESI">Code</a></p>
<h2>III.       Tạo Menu</h2>
<p>Trên các thiết bị di động, việc cung cấp menu options cho các chức năng chính sẽ giúp dễ dàng truy cập hơn là sử dụng các button trên màn hình. Màn hình chịu trách nhiệm xử lý việc hiển thị menu và các menu item để thực thi các chức năng cho ứng dụng.</p>
<h3>1.     Menu item</h3>
<ul>
<li>Các item trong menu là các thể hiện của lớp net.rim.device.api.ui.MenuItem. Lớp này là trừu tượng, và thực thi giao diện Runnable (nó có một phương thức run() mà bạn cần phải thực thi).<br />
Phương thức run() được thực thi trên event thread khi người dùng nhấp vào menu item, vì vậy bạn có thể thay đổi giao diện từ bên trong phương thức run() một cách an toàn. Điều này cũng có nghĩa là bạn không nên thực hiện các xử lý phép toán phức tạp hoặc kết nối mạng trong phương thức run(), thay vào đó bạn tạo một thread mới để thực hiện.</li>
<li>Mỗi menu item đều có ba mẩu thông tin liên kết với nó: chuỗi text để hiển thị, một<br />
thứ tự ưu tiên thực hiện(priority), và vị trí của nó xuất hiện trong menu(ordinal). Priority xác định menu item được highlight khi menu  được xuất hiện lần đầu tiên trên màn hình; item có giá trị thấp nhất thì có quyền ưu tiên cao nhất. Ordinal xác định vị trí mà item sẽ xuất hiện trong menu. Một menu item có giá trị ordinal thấp hơn sẽ nằm gần top của menu. Hai menu item cùng giá trị ordinal sẽ xuất hiện theo thứ tự mà chúng được thêm vào menu, từ trên xuống dưới.</li>
</ul>
<h3>2.     Cài đặt menu item Clear và Login</h3>
<p>Chúng ta sẽ cài đặt 2 menu item trong ứng dụng tương ứng với các acton Login và Clear. Chúng ta sẽ tạo mỗi lớp tương ứng với mỗi menu item và khai báo các lớp là lớp lồng của lớp UiFunMainScreen – bởi vì ta chỉ cần sử dụng chúng để truy cập vào các phương thức private login() và clearTextField().</p>
<p>&nbsp;</p>
<p><em>public class UiFunMainScreen extends MainScreen implements FieldChangeListener { </em></p>
<p><em> class LoginMenuItem extends MenuItem { </em></p>
<p><em> public LoginMenuItem() { </em></p>
<p><em> super(&#8220;Login&#8221;, 20, 10); </em></p>
<p><em> } </em></p>
<p><em> </em></p>
<p><em> public void run() { </em></p>
<p><em> login(); </em></p>
<p><em> } </em></p>
<p><em> } </em></p>
<p><em> </em></p>
<p><em> class ClearMenuItem extends MenuItem { </em></p>
<p><em> public ClearMenuItem() { </em></p>
<p><em> super(&#8220;Clear&#8221;, 10, 20); </em></p>
<p><em> } </em></p>
<p><em> </em></p>
<p><em> public void run() { </em></p>
<p><em> clearTextFields(); </em></p>
<p><em> } </em></p>
<p><em> } </em></p>
<p><em>}</em></p>
<p><strong>Lưu ý</strong> ClearMenuItem có giá trị oridinal thấp hơn và giá trị priority cao hơn LoginMenuItem. Vì vậy, item Clear sẽ nằm phía trên Login trong menu, nhưng item Login sẽ được highlight theo mặc định.</p>
<p>Có vài nơi để chúng ta có thể thêm các menu item. Thứ nhất là trong constructor của Screen, bằng cách gọi phương thức getMenu() và thêm các item vào đối tượng Menu. Thứ hai là ta sẽ override phương thức makeMenu() trong lớp Screen. Trong ví dụ này chúng ta sẽ override phương thức makeMenu() trong lớp UiFunMainScreen như sau:</p>
<p><em>protected void makeMenu(Menu menu, int instance) { </em></p>
<p><em> super.makeMenu(menu, instance); </em></p>
<p><em> menu.add(new LoginMenuItem()); </em></p>
<p><em> menu.add(new ClearMenuItem()); </em></p>
<p><em> }</em></p>
<p>Tùy thuộc vào mục đích của ứng dụng mà chúng ta muốn giữ item Close mặc định mà MainScreen đã đã tự động thêm vào cho chúng ta. Nếu muốn giữ nó thì gọi phương thức super.makeMenu(); ngược lại thì không cần gọi phương thức này.</p>
<p><strong>Lưu ý</strong> Như bạn thấy, ở ví dụ trên chúng ta khai báo các menu item dưới dạng các lớp kế thừa từ lớp MenuItem một cách tường minh; tuy nhiên có một cách viết khác cũng hay được sử dụng đó là khai báo các menu item như là các lớp nội bộ(inner) vô danh, sử dụng cách này thường code ngắn gọn hơn; vì vậy bạn có thể sử dụng một trong 2 cách đã được trình bày. Sau đây là kỹ thuật sử lý lớp inner vô danh:</p>
<p><em>protected void makeMenu(Menu menu, int instance) { </em></p>
<p><em> super.makeMenu(menu, instance); </em></p>
<p><em> menu.add(new MenuItem(&#8220;Login&#8221;, 20, 10) { </em></p>
<p><em> public void run() { </em></p>
<p><em> login(); </em></p>
<p><em> } </em></p>
<p><em> }); </em></p>
<p><em> menu.add(new MenuItem(&#8220;Clear&#8221;, 10, 20) { </em></p>
<p><em> public void run() { </em></p>
<p><em> clearTextFields(); </em></p>
<p><em> } </em></p>
<p><em> }); </em></p>
<p><em> }</em></p>
<h3>3.     Các giá trị intance của Menu</h3>
<p>Tham số <em>instance</em> trong phương thức makeMenu() được sử dụng để xác định menu mà chúng ta sẽ hiển thị. Các ứng dụng BlackBerry hiển thị một vài menu khác nhau tùy thuộc vào menu được hiển thị và context của màn hình và điều khiển. Có các loại instance như sau:</p>
<ul>
<li>Menu.INSTANCE_CONTEXT: menu được hiển thị bằng cách nhấp vào trackball. Thông thường, menu này là một tập hợp các item có sẵn trong menu mặc định được áp dụng đối với control đang được focus hoặc section của màn hình. Ví dụ, Close sẽ không hiển thị ở đây, thay vào đó BlackBerry sẽ tự động thêm một item Full Menu cho menu này, do tham số <em>instance</em> trong phương thức makeMenu() được gán giá trị INSTANCE_DEFAULT.</li>
<li>Menu.INSTANCE_CONTEXT_SELECTION : intance này cũng tương tự như INSTANCE_CONTEXT, nhưng menu được hiển thị khi người dùng có lựa chọn một đoạn văn bản nào đó. Bạn có thể sử dụng instance này khi bạn có thể sao chép văn bản.</li>
<li>Menu.INSTANCE_DEFAULT: Trong trường hợp này, menu được hiển thị bằng cách nhấn vào phím menu trên thiết bị. Menu này sẽ chứa tất cả các item trong context menu, item Close cũng được hiển thị ở đây.</li>
</ul>
<p>Bạn thấy bài viết này thế nào? <em></p>
<p>Các bài liên quan:<br />
</em><a href="../2010/09/19/l%E1%BA%ADp-trinh-v%E1%BB%9Bi-blackberry-ph%E1%BA%A7n-1/">Lập Trình Với Blackberry – Phần 1</a><br />
<a href="http://mobilesprogramming.wordpress.com/2010/12/11/l%E1%BA%ADp-trinh-v%E1%BB%9Bi-blackberry-%E2%80%93-ph%E1%BA%A7n-2/">Lập Trình Với Blackberry – Phần 2</a></p>
<br />Filed under: <a href='http://mobilesprogramming.wordpress.com/category/blackberry/bb-tutorial/'>BB Tutorial</a>, <a href='http://mobilesprogramming.wordpress.com/category/blackberry/'>Blackberry</a> Tagged: <a href='http://mobilesprogramming.wordpress.com/tag/basic-bb/'>basic-BB</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mobilesprogramming.wordpress.com/754/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mobilesprogramming.wordpress.com/754/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mobilesprogramming.wordpress.com/754/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mobilesprogramming.wordpress.com/754/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/mobilesprogramming.wordpress.com/754/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/mobilesprogramming.wordpress.com/754/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/mobilesprogramming.wordpress.com/754/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/mobilesprogramming.wordpress.com/754/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mobilesprogramming.wordpress.com/754/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mobilesprogramming.wordpress.com/754/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mobilesprogramming.wordpress.com/754/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mobilesprogramming.wordpress.com/754/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mobilesprogramming.wordpress.com/754/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mobilesprogramming.wordpress.com/754/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mobilesprogramming.wordpress.com&amp;blog=11410337&amp;post=754&amp;subd=mobilesprogramming&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mobilesprogramming.wordpress.com/2010/12/21/l%e1%ba%adp-trinh-v%e1%bb%9bi-blackberry-%e2%80%93-ph%e1%ba%a7n-3/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/992f5fba26e8af9ebb4a25d922f208c6?s=96&#38;d=&#38;r=G" medium="image">
			<media:title type="html">mobilesprogramming</media:title>
		</media:content>

		<media:content url="http://mobilesprogramming.files.wordpress.com/2010/12/bai26.png?w=220" medium="image">
			<media:title type="html">bai26</media:title>
		</media:content>

		<media:content url="http://mobilesprogramming.files.wordpress.com/2010/12/bai27.png?w=231" medium="image">
			<media:title type="html">bai27</media:title>
		</media:content>
	</item>
		<item>
		<title>Lập Trình Với Blackberry – Phần 2</title>
		<link>http://mobilesprogramming.wordpress.com/2010/12/11/l%e1%ba%adp-trinh-v%e1%bb%9bi-blackberry-%e2%80%93-ph%e1%ba%a7n-2/</link>
		<comments>http://mobilesprogramming.wordpress.com/2010/12/11/l%e1%ba%adp-trinh-v%e1%bb%9bi-blackberry-%e2%80%93-ph%e1%ba%a7n-2/#comments</comments>
		<pubDate>Fri, 10 Dec 2010 17:21:15 +0000</pubDate>
		<dc:creator>mobilesprogramming</dc:creator>
				<category><![CDATA[BB Tutorial]]></category>
		<category><![CDATA[Blackberry]]></category>
		<category><![CDATA[basic-BB]]></category>

		<guid isPermaLink="false">http://mobilesprogramming.wordpress.com/?p=742</guid>
		<description><![CDATA[Bài 2:  Tạo Form Login Sử Dụng Blackberry        Component Các API BlackBerry bao gồm một framework phong phú để xây dựng giao diện người dùng cho các ứng dụng. Trong bài này, chúng ta cùng tìm hiểu cách sử dụng các thành phần giao diện người dùng BlackBerry để xây dựng một ứng dụng với [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mobilesprogramming.wordpress.com&amp;blog=11410337&amp;post=742&amp;subd=mobilesprogramming&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<h1>Bài 2:  Tạo Form Login Sử Dụng Blackberry        Component</h1>
<p>Các API BlackBerry bao gồm một framework phong phú để xây dựng giao diện người dùng cho các ứng dụng. Trong bài này, chúng ta cùng tìm hiểu cách sử dụng các thành phần giao diện người dùng BlackBerry để xây dựng một ứng dụng với một vài màn hình và một số điều khiển để đáp ứng với input của người dùng.</p>
<h2>I.       Các Thành Phần của Blackberry UI</h2>
<p>Tất cả các phần tử trực quan(visible) có thể hiển thị trên màn hình của Blackberry là một trong 3 kiểu sau:</p>
<ul>
<li>Fields: Đây là các khối xây dựng cơ bản của các UI. Nói chung, mỗi control, như một button hoặc text field, sẽ tương ứng với một thể hiện của một Field. Lớp Field sẽ vẽ các điều khiển và xử lý input người dùng.</li>
<li>Managers: Chúng được sử dụng để sắp xếp các Field trên màn hình. Mỗi Field chỉ được chứa trong một và chỉ một Manager. Mỗi Manager thực chất cũng là một Field(lớp này kế thừa từ Field), có nghĩa là mỗi manager có thể chứa các manager khác.</li>
<li>Screens: Chỉ có một screen được active trên một ứng dụng tại mọi thời điểm. Screens xử lý layout của Field thông qua manager và cung cấp các chức năng bổ xung, như</li>
</ul>
<p>Fields được dẫn xuất từ net.rim.device.api.ui.Field. Có rất nhiều Field dựng sẵn hữu ích trong gói net.rim.device.api.ui.component.</p>
<p>Managers được dẫn xuất từ gói net.rim.device.api.ui.Manager, nó kế thừa từ lớp net.rim.device.api.ui.Field. Một số manager hữu ích được định nghĩa trong gói net.rim.device.api.ui.container.</p>
<p>Sreens được dẫn xuất từ gói net.rim.device.api.ui.Screen, nó kế thừa từ lớp Manager. Có một số screen hữu ích trong gói net.rim.device.api.ui.container.<strong> </strong></p>
<p><strong>Lưu ý</strong> Mặc dù Screen kế thừa từ Field, nhưng bạn không thể thêm một Screen vào một Manager.</p>
<h3>1.     Tạo ứng dụng</h3>
<p>Giao diện mà chúng ta sẽ xây dựng như hình vẽ sau:</p>
<p><a href="http://mobilesprogramming.files.wordpress.com/2010/12/bai21.png"><img class="aligncenter size-medium wp-image-743" title="bai21" src="http://mobilesprogramming.files.wordpress.com/2010/12/bai21.png?w=232&#038;h=300" alt="" width="232" height="300" /></a></p>
<p>Bây giờ, ta tạo ra một project UiFun, sau đó tạo ra một package blog.mobileprogramming.uifun; tiếp theo tạo 2 lớp UiFunApplication và UiFunMainScreen.<span id="more-742"></span></p>
<p><strong>package </strong>blog.mobileprogramming.uifun;<em> </em></p>
<p><strong>import</strong> net.rim.device.api.ui.UiApplication;</p>
<p><strong>public</strong> <strong>class</strong> UiFunApplication <strong>extends</strong> UiApplication {</p>
<p><strong>public</strong> UiFunApplication() {</p>
<p>UiFunMainScreen mainScreen = <strong>new</strong> UiFunMainScreen();</p>
<p>pushScreen(mainScreen);</p>
<p>}</p>
<p><strong>public</strong> <strong>static</strong> <strong>void</strong> main(String[] args) {</p>
<p>UiFunApplication app = <strong>new</strong> UiFunApplication();</p>
<p>app.enterEventDispatcher();</p>
<p>}</p>
<p>}<em><br />
</em></p>
<p><strong>package </strong>blog.mobileprogramming.uifun;<em> </em></p>
<p><strong>import </strong>net.rim.device.api.ui.container.MainScreen;<em> </em></p>
<p><strong>public </strong><em>class UiFunMainScreen </em><strong>extends </strong><em>MainScreen { </em></p>
<p><em> </em><strong>public </strong><em>UiFunMainScreen() { </em></p>
<p><em> } </em></p>
<p><em>}</em></p>
<h3>2.     Thêm image Logo</h3>
<p>Đầu tiên, ta thêm một thể hiện net.rim.device.api.ui.component.BitmapField thể show image lên đỉnh màn hình. Các thiết bị Blackberry có thể hiển thị các hình ảnh PNG, JPEG hay GIF, tuy nhiên hầu hết các ứng dụng sử dụng PNGs bởi chúng có kích thước nhỏ, chất lượng cao và hỗ trợ transparent.</p>
<h3>3.     Thêm image vào Project</h3>
<p>Nếu bạn sử dụng JDE Plugin for Eclipse, thêm image vào project Eclipse bằng cách tạo một folder “<strong>res”</strong> cùng cấp với folder “<strong>src”</strong>.</p>
<h3>4.     Thêm image vào Screen</h3>
<p>Tạo một thể hiện BitmapField để thêm vào Screen, trước khi tạo ra thể hiện này, tạo một đối tượng Bitmap         để load image từ resource của project.<em> </em></p>
<p><em>Bitmap logoBitmap = Bitmap.getBitmapResource(&#8220;res/apress_log.png&#8221;);</em></p>
<p><a href="http://mobilesprogramming.files.wordpress.com/2010/12/bai22.png"><img class="aligncenter size-medium wp-image-744" title="bai22" src="http://mobilesprogramming.files.wordpress.com/2010/12/bai22.png?w=220&#038;h=300" alt="" width="220" height="300" /></a></p>
<p>Trong Constructor của lớp UiFunApplication, ta làm như sau:</p>
<p>package blog.mobileprogramming.uifun;</p>
<p><em>import net.rim.device.api.system.Bitmap; </em></p>
<p><em>import net.rim.device.api.ui.Field; </em></p>
<p><em>import net.rim.device.api.ui.component.BitmapField; </em></p>
<p><em>import net.rim.device.api.ui.container.MainScreen; </em></p>
<p><em>public class UiFunMainScreen extends MainScreen { </em></p>
<p><em> BitmapField bitmapField; </em></p>
<p><em> public UiFunMainScreen() { </em></p>
<p><em> Bitmap logoBitmap = Bitmap.getBitmapResource(&#8220;res/apress_logo.png&#8221;); </em></p>
<p><em> bitmapField = new BitmapField(logoBitmap, Field.FIELD_HCENTER); </em></p>
<p><em> add(bitmapField); </em></p>
<p><em> } </em></p>
<p><em>}</em></p>
<p>Bây giờ, nếu bạn chạy ứng dụng sẽ cho giao diện như sau:</p>
<p><a href="http://mobilesprogramming.files.wordpress.com/2010/12/bai23.png"><img class="aligncenter size-medium wp-image-745" title="bai23" src="http://mobilesprogramming.files.wordpress.com/2010/12/bai23.png?w=217&#038;h=300" alt="" width="217" height="300" /></a></p>
<h3>5.     Style Flags của Field</h3>
<p>Hầu như tất cả các Field và Manager đều có một constructor mà có chứa tham số style. Style được đánh dấu bởi các flags style, mỗi style sẽ được sử dụng kết hợp với nhau bởi toán tử “|”. Flags được định nghĩa trong API, mỗi style sẽ có tác động nhất định đến Field hoặc Manage, chẳng hạn như nó quy định vị trí, hành vi&#8230;</p>
<h3>6.     Tạo các Field usename và password</h3>
<p>Ta sẽ sử dụng lớp EditField  để thiết lập usename, PasswordEditField để thiết lập password. Chúng ta không cần sử dụng style đặc biệt cho các Field này.</p>
<p><em>EditField usernameField; </em></p>
<p><em>PasswordEditField passwordField;</em></p>
<p><em>…</em></p>
<p><em>usernameField = new EditField(&#8220;Username:&#8221;, &#8220;&#8221;); </em></p>
<p><em>passwordField = new PasswordEditField(&#8220;Password:&#8221;, &#8220;&#8221;); </em></p>
<p><em>add(usernameField); </em></p>
<p><em>add(passwordField);</em></p>
<h3>7.     Tạo Domain và CheckBox field</h3>
<p>Tạo domain nên sử dụng drop-down list, trong Blackberry API, một giao diện net.rim.device.api.ui.component.ChoiceField sử dụng tương tự như một drop-down list. Bạn có thể thực thi gian diện này một cách trực tiếp, nhưng trong ví dụ này, ta chỉ sử dụng một component thực thi giao diện này, đó là net.rim.device.api.ui.component.</p>
<p>ObjectChoiceField, nếu bạn muốn list các số, sử dụng net.rim.device.api.ui.component.</p>
<p>NumericChoiceField để thay thế.</p>
<p><em>ObjectChoiceField domainField; </em></p>
<p><em>CheckboxField rememberCheckbox;</em></p>
<p><em>…</em></p>
<p><em>domainField = new ObjectChoiceField(&#8220;Domain:&#8221;, new String[] {&#8220;Home&#8221;, &#8220;Work&#8221;}); </em></p>
<p><em>add(domainField);</em></p>
<p><em>rememberCheckbox = new CheckboxField(&#8220;Remember password&#8221;, false); </em></p>
<p><em>add(rememberCheckbox);</em></p>
<h3>8.     Tạo Button</h3>
<p>Để tạo 2 button Clear và Login, ta tạo ra 2 thể hiện từ lớp ButtonField, đồng thời gán vào style là ButtonField.CONSUME_CLICK. Nếu không sử dụng style này, thì sự kiện click sẽ được truyền vào Screen, một menu sẽ được bật lên khi người dùng click vào button, mặc dù button vẫn làm cho action này thực hiện.<br />
BitmapField bitmapField;</p>
<p>EditField usernameField;<em> </em></p>
<p><em><br />
</em>clearButton = <strong>new</strong> ButtonField(&#8220;Clear&#8221;, ButtonField.<em>CONSUME_CLICK</em>);</p>
<p>loginButton = <strong>new</strong> ButtonField(&#8220;Login&#8221;, ButtonField.<em>CONSUME_CLICK</em>);</p>
<p>add(clearButton);</p>
<p>add(loginButton);<em> </em></p>
<p>Tóm lại, code sau khi thêm các thành phần giao diện trong lớp UiFunMainScreen như sau:</p>
<p><strong>package </strong>blog.mobilesprogramming.uifun;</p>
<p><strong>import</strong> net.rim.device.api.system.Bitmap;</p>
<p><strong>import</strong> net.rim.device.api.ui.Field;</p>
<p><strong>import</strong> net.rim.device.api.ui.component.BitmapField;</p>
<p><strong>import</strong> net.rim.device.api.ui.component.ButtonField;</p>
<p><strong>import</strong> net.rim.device.api.ui.component.CheckboxField;</p>
<p><strong>import</strong> net.rim.device.api.ui.component.EditField;</p>
<p><strong>import</strong> net.rim.device.api.ui.component.ObjectChoiceField;</p>
<p><strong>import</strong> net.rim.device.api.ui.component.PasswordEditField;</p>
<p><strong>import</strong> net.rim.device.api.ui.container.MainScreen;</p>
<p><strong>public</strong> <strong>class</strong> UiFunMainScreen <strong>extends</strong> MainScreen {</p>
<p>BitmapField bitmapField;</p>
<p>EditField usernameField;</p>
<p>PasswordEditField passwordField;</p>
<p>ObjectChoiceField domainField;</p>
<p>CheckboxField rememberCheckbox;</p>
<p>ButtonField clearButton;</p>
<p>ButtonField loginButton;</p>
<p><strong>public</strong> UiFunMainScreen() {</p>
<p>Bitmap logoBitmap = Bitmap.<em>getBitmapResource</em>(&#8220;res/apress_logo.png&#8221;);</p>
<p>bitmapField = <strong>new</strong> BitmapField(logoBitmap, Field.<em>FIELD_HCENTER</em>);</p>
<p>add(bitmapField);</p>
<p>usernameField = <strong>new</strong> EditField(&#8220;Username:&#8221;, &#8220;&#8221;);</p>
<p>passwordField = <strong>new</strong> PasswordEditField(&#8220;Password:&#8221;, &#8220;&#8221;);</p>
<p>add(usernameField);</p>
<p>add(passwordField);</p>
<p>domainField = <strong>new</strong> ObjectChoiceField(&#8220;Domain:&#8221;, <strong>new</strong> String[] { &#8220;Home&#8221;,&#8221;Work&#8221; });</p>
<p>add(domainField);</p>
<p>rememberCheckbox = <strong>new</strong> CheckboxField(&#8220;Remember password&#8221;, <strong>false</strong>);</p>
<p>add(rememberCheckbox);</p>
<p>clearButton = <strong>new</strong> ButtonField(&#8220;Clear&#8221;,ButtonField.<em>CONSUME_CLICK</em>);</p>
<p>loginButton = <strong>new</strong> ButtonField(&#8220;Login&#8221;,ButtonField.<em>CONSUME_CLICK</em>);</p>
<p>add(clearButton);</p>
<p>add(loginButton);</p>
<p>}</p>
<p>}</p>
<p>Bây giờ, nếu bạn chạy ứng dụng sẽ như hình vẽ sau:</p>
<p><a href="http://mobilesprogramming.files.wordpress.com/2010/12/bai24.png"><img class="aligncenter size-medium wp-image-746" title="bai24" src="http://mobilesprogramming.files.wordpress.com/2010/12/bai24.png?w=223&#038;h=300" alt="" width="223" height="300" /></a></p>
<h3>9.     Sắp xếp các Button theo chiều ngang</h3>
<p>Lớp UiFunMainScreen trong ví dụ này kế thừa từ MainScreen, nên nó có một trình quản lý layout mặc định là VerticalFieldManager để quản lý các Field. Khi thêm bất kỳ Field nào vào ứng dụng, trình quản lý này sẽ sắp xếp các Field theo chiều dọc. Tuy nhiên trong ví dụ này, ta muốn một số thành phần được sắp xếp theo chiều dọc, riêng các Button thì sẽ sắp xếp theo chiều ngang; để làm được như vậy, chúng ta sẽ sử dụng HorizonetalFieldManager với style là Field.FIELD_RIGHT(canh bên phải) để đẩy các Button vào màn hình.<br />
<em>HorizontalFieldManager buttonManager = new HorizontalFieldManager(Field.FIELD_RIGHT); </em></p>
<p><em>buttonManager.add(clearButton); </em></p>
<p><em>buttonManager.add(loginButton); </em></p>
<p><em>add(buttonManager);</em></p>
<p>Ngoài ra, ta sẽ sử dụng thêm một đối tượng SeparatorField để vẽ một thanh chắn ngang bên dưới image với các Field của ứng dụng.</p>
<p><em>Bitmap logoBitmap = Bitmap.getBitmapResource(&#8220;res/apress_logo.png&#8221;); </em></p>
<p><em> bitmapField = new BitmapField(logoBitmap, Field.FIELD_HCENTER); </em></p>
<p><em> add(bitmapField); </em></p>
<p><em> add(new SeparatorField()); </em></p>
<p><em> add(new LabelField(&#8220;Please enter your credentials:&#8221;)); </em></p>
<p><em> </em></p>
<p><em> usernameField = new EditField(&#8220;Username:&#8221;, &#8220;&#8221;); </em></p>
<p><em> passwordField = new PasswordEditField(&#8220;Password:&#8221;, &#8220;&#8221;); </em></p>
<p><em> add(usernameField); </em></p>
<p><em> add(passwordField); </em></p>
<p><em> </em></p>
<p><em> domainField = new ObjectChoiceField(&#8220;Domain:&#8221;, new String[] {&#8220;Home&#8221;, &#8220;Work&#8221;}); </em></p>
<p><em> add(domainField); </em></p>
<p><em> </em></p>
<p><em> rememberCheckbox = new CheckboxField(&#8220;Remember password:&#8221;, false); </em></p>
<p><em> add(rememberCheckbox); </em></p>
<p><em> </em></p>
<p><em> add(new SeparatorField()); </em></p>
<p><em> </em></p>
<p><em> clearButton = new ButtonField(&#8220;Clear&#8221;, ButtonField.CONSUME_CLICK); </em></p>
<p><em> loginButton = new ButtonField(&#8220;Login&#8221;, ButtonField.CONSUME_CLICK); </em></p>
<p><em> </em></p>
<p><em> HorizontalFieldManager buttonManager = </em></p>
<p><em> new HorizontalFieldManager(Field.FIELD_RIGHT); </em></p>
<p><em> buttonManager.add(clearButton); </em></p>
<p><em> buttonManager.add(loginButton); </em></p>
<p><em> add(buttonManager);</em></p>
<p>Bây giờ, nếu bạn chạy đoạn code trên, nó sẽ như hình vẽ sau:</p>
<p><a href="http://mobilesprogramming.files.wordpress.com/2010/12/bai25.png"><img class="aligncenter size-medium wp-image-747" title="bai25" src="http://mobilesprogramming.files.wordpress.com/2010/12/bai25.png?w=228&#038;h=300" alt="" width="228" height="300" /></a><br />
Bạn thấy bài viết này thế nào?</p>
<p><em>Các bài liên quan:<br />
</em><a href="http://mobilesprogramming.wordpress.com/2010/09/19/l%E1%BA%ADp-trinh-v%E1%BB%9Bi-blackberry-ph%E1%BA%A7n-1/">Lập Trình Với Blackberry – Phần 1</a><br />
<a href="http://mobilesprogramming.wordpress.com/2010/12/21/l%E1%BA%ADp-trinh-v%E1%BB%9Bi-blackberry-%E2%80%93-ph%E1%BA%A7n-3/">Lập Trình Với Blackberry – Phần 3</a></p>
<br />Filed under: <a href='http://mobilesprogramming.wordpress.com/category/blackberry/bb-tutorial/'>BB Tutorial</a>, <a href='http://mobilesprogramming.wordpress.com/category/blackberry/'>Blackberry</a> Tagged: <a href='http://mobilesprogramming.wordpress.com/tag/basic-bb/'>basic-BB</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mobilesprogramming.wordpress.com/742/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mobilesprogramming.wordpress.com/742/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mobilesprogramming.wordpress.com/742/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mobilesprogramming.wordpress.com/742/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/mobilesprogramming.wordpress.com/742/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/mobilesprogramming.wordpress.com/742/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/mobilesprogramming.wordpress.com/742/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/mobilesprogramming.wordpress.com/742/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mobilesprogramming.wordpress.com/742/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mobilesprogramming.wordpress.com/742/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mobilesprogramming.wordpress.com/742/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mobilesprogramming.wordpress.com/742/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mobilesprogramming.wordpress.com/742/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mobilesprogramming.wordpress.com/742/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mobilesprogramming.wordpress.com&amp;blog=11410337&amp;post=742&amp;subd=mobilesprogramming&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mobilesprogramming.wordpress.com/2010/12/11/l%e1%ba%adp-trinh-v%e1%bb%9bi-blackberry-%e2%80%93-ph%e1%ba%a7n-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/992f5fba26e8af9ebb4a25d922f208c6?s=96&#38;d=&#38;r=G" medium="image">
			<media:title type="html">mobilesprogramming</media:title>
		</media:content>

		<media:content url="http://mobilesprogramming.files.wordpress.com/2010/12/bai21.png?w=232" medium="image">
			<media:title type="html">bai21</media:title>
		</media:content>

		<media:content url="http://mobilesprogramming.files.wordpress.com/2010/12/bai22.png?w=220" medium="image">
			<media:title type="html">bai22</media:title>
		</media:content>

		<media:content url="http://mobilesprogramming.files.wordpress.com/2010/12/bai23.png?w=217" medium="image">
			<media:title type="html">bai23</media:title>
		</media:content>

		<media:content url="http://mobilesprogramming.files.wordpress.com/2010/12/bai24.png?w=223" medium="image">
			<media:title type="html">bai24</media:title>
		</media:content>

		<media:content url="http://mobilesprogramming.files.wordpress.com/2010/12/bai25.png?w=228" medium="image">
			<media:title type="html">bai25</media:title>
		</media:content>
	</item>
		<item>
		<title>Blackberry Browser API &#8211; Phần 2</title>
		<link>http://mobilesprogramming.wordpress.com/2010/11/15/blackberry-browser-api-ph%e1%ba%a7n-2/</link>
		<comments>http://mobilesprogramming.wordpress.com/2010/11/15/blackberry-browser-api-ph%e1%ba%a7n-2/#comments</comments>
		<pubDate>Mon, 15 Nov 2010 16:48:46 +0000</pubDate>
		<dc:creator>mobilesprogramming</dc:creator>
		
		<guid isPermaLink="false">http://mobilesprogramming.wordpress.com/?p=733</guid>
		<description><![CDATA[IV.Hỗ Trợ Các Kiểu MIME Bổ Xung Để thiết lập các kiểu MIME bổ xung cho Browser, bạn sử dụng gói net.rim.device.api.browser.plugin, cho phép các ứng dụng của bên thứ 3 đăng ký chúng với thư viện rendering như là một provider rendering cho các kiểu MIME không được browser trên thiết bị Blackberry hỗ [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mobilesprogramming.wordpress.com&amp;blog=11410337&amp;post=733&amp;subd=mobilesprogramming&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<h2>IV.Hỗ Trợ Các Kiểu MIME Bổ Xung</h2>
<p>Để thiết lập các kiểu MIME bổ xung cho Browser, bạn sử dụng gói net.rim.device.api.browser.plugin, cho phép các ứng dụng của bên thứ 3 đăng ký chúng với thư viện rendering như là một provider rendering cho các kiểu MIME không được browser trên thiết bị Blackberry hỗ trợ.</p>
<p><strong>Lưu ý </strong>Phương thức BrowserFieldProviderRegistry.registry() sẽ ném ra một exception nếu bạn cố gắng đăng ký một kiểu MIME mà đã được thiết bị Blackberry hỗ trợ. Để nhận biết được danh sách các kiểu MIME được thiết bị Blackberry hỗ trợ, gọi phương thức RenderingSession.getSupportMimeType().</p>
<h3>1.Đăng ký provider rendering cho một kiểu MIME</h3>
<p>Để hỗ trợ các kiểu MIME bổ xung, kế thừa lớp abstract BrowserContentProvider. Để xác định các đặc tính hiển thị như: không có srollbar hay full màn hình, bạn thực thi giao diện BrowserPageContext. Thư viện rendering gọi phương thức BrowserContentProvider.accept() và BrowserContentProvider.getSupportedMimeTypes() để xác định các kiểu MIME cho provider rendering.</p>
<h4>1.1.List danh sách các kiểu MIME chấp nhận</h4>
<p>Cài đặt phương thức getAccept() và getSupportedMimeTypes() để list ra danh sách các các kiểu MIME mà provider có thể chấp nhận như là một tập hợp các tùy chọn rendering. Phương thức getAccept() xem xét các tùy chọn rendering được thiết lập.<span id="more-733"></span></p>
<p>Ví dụ 7:</p>
<p>public String[] getAccept(RenderingOptions context) {</p>
<p>// Return subset of getSupportedMimeTypes() if accept depends on rendering</p>
<p>// options. For example, HTML can be turned off in the rendering options.</p>
<p>// This would cause HTMLConverter to remove HTML MIME types.</p>
<p>return ACCEPT;</p>
<p>}</p>
<p>public String[] getSupportedMimeTypes() {</p>
<p>return ACCEPT;</p>
<p>}</p>
<h4>1.2.Xác định các đặc tính hiển thị</h4>
<p>Thực thi giao diện BrowserPageContext để xác định các đặc tính hiển thị. Nếu bạn không thực thi giao diện này, các giá trị mặc định sẽ được sử dụng.</p>
<p>Ví dụ 8:</p>
<p>public boolean getPropertyWithBooleanValue(int id, boolean defaultValue) {</p>
<p>// TODO Implement.</p>
<p>return false;</p>
<p>}</p>
<p>public int getPropertyWithIntValue(int id, int defaultValue) {</p>
<p>if (id == BrowserPageContext.DISPLAY_STYLE) {</p>
<p>// Turn off the scroll bar.</p>
<p>return BrowserPageContext.STYLE_NO_VERTICAL_SCROLLBAR;</p>
<p>}</p>
<p>return 0;</p>
<p>}</p>
<p>public Object getPropertyWithObjectValue(int id, Object defaultValue) {</p>
<p>// TODO Implement.</p>
<p>return null;</p>
<p>}</p>
<p>public String getPropertyWithStringValue(int id, String defaultValue) {</p>
<p>// TODO Implement.</p>
<p>return null;</p>
<p>}</p>
<h4>1.3.Nhận một field để trình diễn nội dung</h4>
<p>Cài đặt phương thức getBrowserContent().</p>
<p>Ví dụ 9:</p>
<p>public BrowserContent getBrowserContent( BrowserContentProviderContext context) throws RenderingException {</p>
<p>if (context == null) {</p>
<p>throw new RenderingException(&#8220;No Context is passed into Provider&#8221;);</p>
<p>}</p>
<p>BrowserContentBaseImpl browserContentBaseImpl = new</p>
<p>BrowserContentBaseImpl(context.getHttpConnection().getURL(), null,</p>
<p>context.getRenderingApplication(),</p>
<p>context.getRenderingSession().getRenderingOptions(), context.getFlags());</p>
<p>VerticalFieldManager vfm = new VerticalFieldManager(Manager.VERTICAL_SCROLL);</p>
<p>vfm.add(new LabelField(&#8220;Mime type: &#8220;) );</p>
<p>vfm.add(new LabelField(ACCEPT[0]));</p>
<p>vfm.add(new SeparatorField());</p>
<p>vfm.add(new LabelField(&#8220;Content of the resource file: \n&#8221;));</p>
<p>vfm.add(new SeparatorField());</p>
<p>try {</p>
<p>HttpConnection conn = context.getHttpConnection();</p>
<p>InputStream in = conn.openInputStream();</p>
<p>byte[] data = IOUtilities.streamToBytes(in);</p>
<p>vfm.add(new LabelField(new String(data)));</p>
<p>} catch (IOException e) {</p>
<p>// TODO Implement.</p>
<p>e.printStackTrace();</p>
<p>}</p>
<p>browserContentBaseImpl.setContent(vfm);</p>
<p>browserContentBaseImpl.setTitle(ACCEPT[0]);</p>
<p>// Set browser page context, this will tell the browser how to display this</p>
<p>// field.</p>
<p>browserContentBaseImpl.setBrowserPageContext(this);</p>
<p>return browserContentBaseImpl;</p>
<p>}</p>
<h4>1.4.Đăng kí khi thiết bị Blackberry bắt đầu</h4>
<p>Tạo một project library và thiết lập các thuộc tính của nó để auto-run khi bắt đầu. Trong phương thức libMain(String[] args) bạn cài đặt như sau:</p>
<p>public static void libMain( String[] args ) {</p>
<p>BrowserContentProviderRegistry converterRegistry =</p>
<p>BrowserContentProviderRegistry.getInstance();</p>
<p>if (converterRegistry != null) {</p>
<p>converterRegistry.register(new BrowserPlugin());</p>
<p>}</p>
<p>}</p>
<h3>2.Ví dụ:</h3>
<p>Ví dụ này gồm 3 file: BrowserFieldSampleApplication.java, Utilities.java và SecondaryResourceFetchThread.</p>
<p><strong>package</strong> blog.mobilesprogramming;</p>
<p><strong>import</strong> java.io.IOException;</p>
<p><strong>import</strong> javax.microedition.io.HttpConnection;</p>
<p><strong>import</strong> net.rim.device.api.browser.field.*;</p>
<p><strong>import</strong> net.rim.device.api.io.http.HttpHeaders;</p>
<p><strong>import</strong> net.rim.device.api.system.Application;</p>
<p><strong>import</strong> net.rim.device.api.ui.*;</p>
<p><strong>import</strong> net.rim.device.api.ui.component.Status;</p>
<p><strong>import</strong> net.rim.device.api.ui.container.MainScreen;</p>
<p>/**</p>
<p>*</p>
<p>*/</p>
<p><strong>final</strong> <strong>public</strong> <strong>class</strong> BrowserFieldSampleApplication <strong>extends</strong> UiApplication <strong>implements</strong> RenderingApplication {</p>
<p><strong>private</strong> <strong>static</strong> <strong>final</strong> String <em>REFERER</em> = &#8220;referer&#8221;;</p>
<p><strong>private</strong> RenderingSession _renderingSession;</p>
<p><strong>private</strong> MainScreen _mainScreen;</p>
<p><strong>private</strong> HttpConnection  _currentConnection;</p>
<p>/***************************************************************************</p>
<p>* Main.</p>
<p>**************************************************************************/</p>
<p><strong>public</strong> <strong>static</strong> <strong>void</strong> main(String[] args) {</p>
<p>BrowserFieldSampleApplication app = <strong>new</strong> BrowserFieldSampleApplication();</p>
<p>app.enterEventDispatcher();</p>
<p>}</p>
<p><strong>private</strong> BrowserFieldSampleApplication() {</p>
<p>_mainScreen = <strong>new</strong> MainScreen();</p>
<p>pushScreen(_mainScreen);</p>
<p>_renderingSession = RenderingSession.<em>getNewInstance</em>();</p>
<p>// enable <span style="text-decoration:underline;">javascript</span></p>
<p>//_renderingSession.getRenderingOptions().setProperty(RenderingOptions.CORE_OPTIONS_GUID, RenderingOptions.JAVASCRIPT_ENABLED, true);</p>
<p>PrimaryResourceFetchThread thread = <strong>new</strong> PrimaryResourceFetchThread(&#8220;http://www.google.com&#8221;, <strong>null</strong>, <strong>null</strong>, <strong>null</strong>, <strong>this</strong>);</p>
<p>thread.start();</p>
<p>}</p>
<p><strong>public</strong> <strong>void</strong> processConnection(HttpConnection connection, Event e) {</p>
<p>// cancel previous request</p>
<p><strong>if</strong> (_currentConnection != <strong>null</strong>) {</p>
<p><strong>try</strong> {</p>
<p>_currentConnection.close();</p>
<p>} <strong>catch</strong> (IOException e1) {</p>
<p>}</p>
<p>}</p>
<p>_currentConnection = connection;</p>
<p>BrowserContent browserContent = <strong>null</strong>;</p>
<p><strong>try</strong> {</p>
<p>browserContent = _renderingSession.getBrowserContent(connection, <strong>this</strong>, e);</p>
<p><strong>if</strong> (browserContent != <strong>null</strong>) {</p>
<p>Field field = browserContent.getDisplayableContent();</p>
<p><strong>if</strong> (field != <strong>null</strong>) {</p>
<p><strong>synchronized</strong> (Application.<em>getEventLock</em>()) {</p>
<p>_mainScreen.deleteAll();</p>
<p>_mainScreen.add(field);</p>
<p>}</p>
<p>}</p>
<p>browserContent.finishLoading();</p>
<p>}</p>
<p>} <strong>catch</strong> (RenderingException re) {</p>
<p>} <strong>finally</strong> {</p>
<p>SecondaryResourceFetchThread.<em>doneAddingImages</em>();</p>
<p>}</p>
<p>}</p>
<p>/**</p>
<p>* <strong>@see</strong> net.rim.device.api.browser.RenderingApplication#eventOccurred(net.rim.device.api.browser.Event)</p>
<p>*/</p>
<p><strong>public</strong> Object eventOccurred(Event event) {</p>
<p><strong>int</strong> eventId = event.getUID();</p>
<p><strong>switch</strong> (eventId) {</p>
<p><strong>case</strong> Event.<em>EVENT_URL_REQUESTED</em> : {</p>
<p>UrlRequestedEvent urlRequestedEvent = (UrlRequestedEvent) event;</p>
<p>String <span style="text-decoration:underline;">absoluteUrl</span> = urlRequestedEvent.getURL();</p>
<p>HttpConnection <span style="text-decoration:underline;">conn</span> = <strong>null</strong>;</p>
<p>PrimaryResourceFetchThread thread = <strong>new</strong> PrimaryResourceFetchThread(urlRequestedEvent.getURL(),</p>
<p>urlRequestedEvent.getHeaders(),</p>
<p>urlRequestedEvent.getPostData(),</p>
<p>event, <strong>this</strong>);</p>
<p>thread.start();</p>
<p><strong>break</strong>;</p>
<p>} <strong>case</strong> Event.<em>EVENT_BROWSER_CONTENT_CHANGED</em>: {</p>
<p>// browser field title might have changed update title</p>
<p>BrowserContentChangedEvent browserContentChangedEvent = (BrowserContentChangedEvent) event;</p>
<p><strong>if</strong> (browserContentChangedEvent.getSource() <strong>instanceof</strong> BrowserContent) {</p>
<p>BrowserContent browserField = (BrowserContent) browserContentChangedEvent.getSource();</p>
<p>String newTitle = browserField.getTitle();</p>
<p><strong>if</strong> (newTitle != <strong>null</strong>) {</p>
<p>_mainScreen.setTitle(newTitle);</p>
<p>}</p>
<p>}</p>
<p><strong>break</strong>;</p>
<p>} <strong>case</strong> Event.<em>EVENT_REDIRECT</em> : {</p>
<p>RedirectEvent e = (RedirectEvent) event;</p>
<p>String referrer = e.getSourceURL();</p>
<p><strong>switch</strong> (e.getType()) {</p>
<p><strong>case</strong> RedirectEvent.<em>TYPE_SINGLE_FRAME_REDIRECT</em> :</p>
<p>// show redirect message</p>
<p>Application.<em>getApplication</em>().invokeAndWait(<strong>new</strong> Runnable() {</p>
<p><strong>public</strong> <strong>void</strong> run() {</p>
<p>Status.<em>show</em>(&#8220;You are being redirected to a different page&#8230;&#8221;);</p>
<p>}</p>
<p>});</p>
<p><strong>break</strong>;</p>
<p><strong>case</strong> RedirectEvent.<em>TYPE_JAVASCRIPT</em> :</p>
<p><strong>break</strong>;</p>
<p><strong>case</strong> RedirectEvent.<em>TYPE_META</em> :</p>
<p>// MSIE and <span style="text-decoration:underline;">Mozilla</span> don&#8217;t send a <span style="text-decoration:underline;">Referer</span> for META Refresh.</p>
<p>referrer = <strong>null</strong>;</p>
<p><strong>break</strong>;</p>
<p><strong>case</strong> RedirectEvent.<em>TYPE_300_REDIRECT</em> :</p>
<p>// MSIE, <span style="text-decoration:underline;">Mozilla</span>, and Opera all send the original</p>
<p>// request&#8217;s <span style="text-decoration:underline;">Referer</span> as the <span style="text-decoration:underline;">Referer</span> for the new</p>
<p>// request.</p>
<p>Object eventSource = e.getSource();</p>
<p><strong>if</strong> (eventSource <strong>instanceof</strong> HttpConnection) {</p>
<p>referrer = ((HttpConnection)eventSource).getRequestProperty(<em>REFERER</em>);</p>
<p>}</p>
<p><strong>break</strong>;</p>
<p>}</p>
<p>HttpHeaders requestHeaders = <strong>new</strong> HttpHeaders();</p>
<p>requestHeaders.setProperty(<em>REFERER</em>, referrer);</p>
<p>PrimaryResourceFetchThread thread = <strong>new</strong> PrimaryResourceFetchThread(e.getLocation(), requestHeaders,<strong>null</strong>, event, <strong>this</strong>);</p>
<p>thread.start();</p>
<p><strong>break</strong>;</p>
<p>} <strong>case</strong> Event.<em>EVENT_CLOSE</em> :</p>
<p>// <strong>TODO</strong>: close the <span style="text-decoration:underline;">appication</span></p>
<p><strong>break</strong>;</p>
<p><strong>case</strong> Event.<em>EVENT_SET_HEADER</em> :        // no cache support</p>
<p><strong>case</strong> Event.<em>EVENT_SET_HTTP_COOKIE</em> :   // no cookie support</p>
<p><strong>case</strong> Event.<em>EVENT_HISTORY</em> :           // no history support</p>
<p><strong>case</strong> Event.<em>EVENT_EXECUTING_SCRIPT</em> :  // no progress bar is supported</p>
<p><strong>case</strong> Event.<em>EVENT_FULL_WINDOW</em> :       // no full window support</p>
<p><strong>case</strong> Event.<em>EVENT_STOP</em> :              // no stop loading support</p>
<p><strong>default</strong> :</p>
<p>}</p>
<p><strong>return</strong> <strong>null</strong>;</p>
<p>}</p>
<p>/**</p>
<p>* <strong>@see</strong> net.rim.device.api.browser.RenderingApplication#getAvailableHeight(net.rim.device.api.browser.BrowserContent)</p>
<p>*/</p>
<p><strong>public</strong> <strong>int</strong> getAvailableHeight(BrowserContent browserField) {</p>
<p>// field has full screen</p>
<p><strong>return</strong> <span style="text-decoration:underline;">Graphics.<span style="text-decoration:line-through;">getScreenHeight</span>()</span>;</p>
<p>}</p>
<p>/**</p>
<p>* <strong>@see</strong> net.rim.device.api.browser.RenderingApplication#getAvailableWidth(net.rim.device.api.browser.BrowserContent)</p>
<p>*/</p>
<p><strong>public</strong> <strong>int</strong> getAvailableWidth(BrowserContent browserField) {</p>
<p>// field has full screen</p>
<p><strong>return</strong> <span style="text-decoration:underline;">Graphics.<span style="text-decoration:line-through;">getScreenWidth</span>()</span>;</p>
<p>}</p>
<p>/**</p>
<p>* <strong>@see</strong> net.rim.device.api.browser.RenderingApplication#getHistoryPosition(net.rim.device.api.browser.BrowserContent)</p>
<p>*/</p>
<p><strong>public</strong> <strong>int</strong> getHistoryPosition(BrowserContent browserField) {</p>
<p>// no history support</p>
<p><strong>return</strong> 0;</p>
<p>}</p>
<p>/**</p>
<p>* <strong>@see</strong> net.rim.device.api.browser.RenderingApplication#getHTTPCookie(java.lang.String)</p>
<p>*/</p>
<p><strong>public</strong> String getHTTPCookie(String url) {</p>
<p>// no cookie support</p>
<p><strong>return</strong> <strong>null</strong>;</p>
<p>}</p>
<p>/**</p>
<p>* <strong>@see</strong> net.rim.device.api.browser.RenderingApplication#getResource(net.rim.device.api.browser.RequestedResource,</p>
<p>*      net.rim.device.<span style="text-decoration:underline;">api</span>.browser.BrowserContent)</p>
<p>*/</p>
<p><strong>public</strong> HttpConnection getResource( RequestedResource resource, BrowserContent referrer) {</p>
<p><strong>if</strong> (resource == <strong>null</strong>) {</p>
<p><strong>return</strong> <strong>null</strong>;</p>
<p>}</p>
<p>// check if this is cache-only request</p>
<p><strong>if</strong> (resource.isCacheOnly()) {</p>
<p>// no cache support</p>
<p><strong>return</strong> <strong>null</strong>;</p>
<p>}</p>
<p>String url = resource.getUrl();</p>
<p><strong>if</strong> (url == <strong>null</strong>) {</p>
<p><strong>return</strong> <strong>null</strong>;</p>
<p>}</p>
<p>// if referrer is null we must return the connection</p>
<p><strong>if</strong> (referrer == <strong>null</strong>) {</p>
<p>HttpConnection connection = Utilities.<em>makeConnection</em>(resource.getUrl(), resource.getRequestHeaders(), <strong>null</strong>);</p>
<p><strong>return</strong> connection;</p>
<p>} <strong>else</strong> {</p>
<p>// if referrer is provided we can set up the connection on a separate thread</p>
<p>SecondaryResourceFetchThread.<em>enqueue</em>(resource, referrer);</p>
<p>}</p>
<p><strong>return</strong> <strong>null</strong>;</p>
<p>}</p>
<p>/**</p>
<p>* <strong>@see</strong> net.rim.device.api.browser.RenderingApplication#invokeRunnable(java.lang.Runnable)</p>
<p>*/</p>
<p><strong>public</strong> <strong>void</strong> invokeRunnable(Runnable runnable) {</p>
<p>(<strong>new</strong> Thread(runnable)).run();</p>
<p>}</p>
<p>}</p>
<p><strong>class</strong> PrimaryResourceFetchThread <strong>extends</strong> Thread {</p>
<p><strong>private</strong> BrowserFieldSampleApplication _application;</p>
<p><strong>private</strong> Event _event;</p>
<p><strong>private</strong> <strong>byte</strong>[] _postData;</p>
<p><strong>private</strong> HttpHeaders _requestHeaders;</p>
<p><strong>private</strong> String _url;</p>
<p>PrimaryResourceFetchThread(String url, HttpHeaders requestHeaders, <strong>byte</strong>[] postData,</p>
<p>Event event, BrowserFieldSampleApplication application) {</p>
<p>_url = url;</p>
<p>_requestHeaders = requestHeaders;</p>
<p>_postData = postData;</p>
<p>_application = application;</p>
<p>_event = event;</p>
<p>}</p>
<p><strong>public</strong> <strong>void</strong> run() {</p>
<p>HttpConnection connection = Utilities.<em>makeConnection</em>(_url, _requestHeaders, _postData);</p>
<p>_application.processConnection(connection, _event);</p>
<p>}</p>
<p>}</p>
<p><strong>package</strong> blog.mobilesprogramming;</p>
<p><strong>import</strong> java.util.Vector;</p>
<p><strong>import</strong> javax.microedition.io.HttpConnection;</p>
<p><strong>import</strong> net.rim.device.api.browser.field.BrowserContent;</p>
<p><strong>import</strong> net.rim.device.api.browser.field.RequestedResource;</p>
<p>/**</p>
<p>*</p>
<p>*/</p>
<p><strong>class</strong> SecondaryResourceFetchThread <strong>extends</strong> Thread {</p>
<p>/**</p>
<p>* <span style="text-decoration:underline;">Callback</span> browser field</p>
<p>*/</p>
<p><strong>private</strong> BrowserContent    _browserField;</p>
<p>/**</p>
<p>* Images to retrieve</p>
<p>*/</p>
<p><strong>private</strong> Vector            _imageQueue;</p>
<p>/**</p>
<p>* True is all images have been enqueued</p>
<p>*/</p>
<p><strong>private</strong> <strong>boolean</strong> _done;</p>
<p>/**</p>
<p>* Sync object</p>
<p>*/</p>
<p><strong>private</strong> <strong>static</strong> Object     <em>_syncObject</em> = <strong>new</strong> Object();</p>
<p>/**</p>
<p>* Secondary thread</p>
<p>*/</p>
<p><strong>private</strong> <strong>static</strong> SecondaryResourceFetchThread <em>_currentThread</em>;</p>
<p>/**</p>
<p>* Enqueues secondary resource for a browser field.</p>
<p>*</p>
<p>* <strong>@param</strong> resource &#8211; resource to retrieve</p>
<p>* <strong>@param</strong> referrer &#8211; call back <span style="text-decoration:underline;">browsr</span> field</p>
<p>*/</p>
<p><strong>public</strong> <strong>static</strong> <strong>void</strong> enqueue(RequestedResource resource, BrowserContent referrer) {</p>
<p><strong>if</strong> (resource == <strong>null</strong>) {</p>
<p><strong>return</strong>;</p>
<p>}</p>
<p><strong>synchronized</strong>( <em>_syncObject</em> ) {</p>
<p>// create new thread</p>
<p><strong>if</strong> (<em>_currentThread</em> == <strong>null</strong>) {</p>
<p><em>_currentThread</em> = <strong>new</strong> SecondaryResourceFetchThread();</p>
<p><em>_currentThread</em>.start();</p>
<p>} <strong>else</strong> {</p>
<p>// if thread <span style="text-decoration:underline;">alread</span> is running, check that we are adding images for the same browser field</p>
<p><strong>if</strong> (referrer != <em>_currentThread</em>._browserField) {</p>
<p><strong>synchronized</strong>( <em>_currentThread</em>._imageQueue) {</p>
<p>// if the request is for a different browser field,</p>
<p>// clear old elements</p>
<p><em>_currentThread</em>._imageQueue.removeAllElements();</p>
<p>}</p>
<p>}</p>
<p>}</p>
<p><strong>synchronized</strong>( <em>_currentThread</em>._imageQueue) {</p>
<p><em>_currentThread</em>._imageQueue.addElement(resource);</p>
<p>}</p>
<p><em>_currentThread</em>._browserField = referrer;</p>
<p>}</p>
<p>}</p>
<p>/**</p>
<p>* Constructor</p>
<p>*</p>
<p>*/</p>
<p><strong>private</strong> SecondaryResourceFetchThread() {</p>
<p>_imageQueue = <strong>new</strong> Vector();</p>
<p>}</p>
<p>/**</p>
<p>* Indicate that all images have been enqueued for this browser field</p>
<p>*/</p>
<p><strong>public</strong> <strong>static</strong> <strong>void</strong> doneAddingImages() {</p>
<p><strong>synchronized</strong>( <em>_syncObject</em> ) {</p>
<p><strong>if</strong> (<em>_currentThread</em> != <strong>null</strong>) {</p>
<p><em>_currentThread</em>._done = <strong>true</strong>;</p>
<p>}</p>
<p>}</p>
<p>}</p>
<p><strong>public</strong> <strong>void</strong> run() {</p>
<p><strong>while</strong> (<strong>true</strong>) {</p>
<p><strong>if</strong> (_done) {</p>
<p>// check if we are done requesting images</p>
<p><strong>synchronized</strong>( <em>_syncObject</em> ) {</p>
<p><strong>synchronized</strong>( _imageQueue ) {</p>
<p><strong>if</strong> (_imageQueue.size() == 0) {</p>
<p><em>_currentThread</em> = <strong>null</strong>;</p>
<p><strong>break</strong>;</p>
<p>}</p>
<p>}</p>
<p>}</p>
<p>}</p>
<p>RequestedResource resource = <strong>null</strong>;</p>
<p>// request next image</p>
<p><strong>synchronized</strong>( _imageQueue ) {</p>
<p><strong>if</strong> (_imageQueue.size() &gt; 0) {</p>
<p>resource = (RequestedResource)_imageQueue.elementAt(0);</p>
<p>_imageQueue.removeElementAt(0);</p>
<p>}</p>
<p>}</p>
<p><strong>if</strong> (resource != <strong>null</strong>) {</p>
<p>HttpConnection connection = Utilities.<em>makeConnection</em>(resource.getUrl(), resource.getRequestHeaders(), <strong>null</strong>);</p>
<p>resource.setHttpConnection(connection);</p>
<p>// signal to the browser field that resource is ready</p>
<p><strong>if</strong> (_browserField != <strong>null</strong>) {</p>
<p>_browserField.resourceReady(resource);</p>
<p>}</p>
<p>}</p>
<p>}</p>
<p>}</p>
<p>}</p>
<p><strong>package</strong> blog.mobilesprogramming;</p>
<p><strong>import</strong> java.io.IOException;</p>
<p><strong>import</strong> java.io.OutputStream;</p>
<p><strong>import</strong> javax.microedition.io.Connector;</p>
<p><strong>import</strong> javax.microedition.io.HttpConnection;</p>
<p><strong>import</strong> net.rim.device.api.io.http.HttpHeaders;</p>
<p><strong>import</strong> net.rim.device.api.io.http.HttpProtocolConstants;</p>
<p><strong>import</strong> net.rim.device.api.util.StringUtilities;</p>
<p>/**</p>
<p>*</p>
<p>*/</p>
<p><strong>public</strong> <strong>class</strong> Utilities {</p>
<p><strong>public</strong> <strong>static</strong> HttpConnection makeConnection(String url, HttpHeaders requestHeaders, <strong>byte</strong>[] postData) {</p>
<p>HttpConnection conn = <strong>null</strong>;</p>
<p>OutputStream out = <strong>null</strong>;</p>
<p><strong>try</strong> {</p>
<p>conn = (HttpConnection) Connector.<em>open</em>(url);</p>
<p><strong>if</strong> (requestHeaders != <strong>null</strong>) {</p>
<p>// From</p>
<p>// http://www.w3.org/Protocols/rfc2616/rfc2616-sec15.html#sec15.1.3</p>
<p>//</p>
<p>//     Clients SHOULD NOT include a <span style="text-decoration:underline;">Referer</span> header</p>
<p>//     field in a (non-secure) HTTP request if the</p>
<p>//     referring page was transferred with a secure</p>
<p>//     protocol.</p>
<p>String referer = requestHeaders.getPropertyValue(&#8220;referer&#8221;);</p>
<p><strong>boolean</strong> sendReferrer = <strong>true</strong>;</p>
<p><strong>if</strong> (referer != <strong>null</strong> &amp;&amp; StringUtilities.<em>startsWithIgnoreCase</em>(referer, &#8220;https:&#8221;) &amp;&amp; !StringUtilities.<em>startsWithIgnoreCase</em>(url, &#8220;https:&#8221;)) {</p>
<p>sendReferrer = <strong>false</strong>;</p>
<p>}</p>
<p><strong>int</strong> size = requestHeaders.size();</p>
<p><strong>for</strong> (<strong>int</strong> i = 0; i &lt; size;) {</p>
<p>String header = requestHeaders.getPropertyKey(i);</p>
<p>// remove <span style="text-decoration:underline;">referer</span> header if needed</p>
<p><strong>if</strong> ( !sendReferrer &amp;&amp; header.equals(&#8220;referer&#8221;)) {</p>
<p>requestHeaders.removeProperty(i);</p>
<p>&#8211;size;</p>
<p><strong>continue</strong>;</p>
<p>}</p>
<p>String value = requestHeaders.getPropertyValue( i++ );</p>
<p><strong>if</strong> (value != <strong>null</strong>) {</p>
<p>conn.setRequestProperty( header, value);</p>
<p>}</p>
<p>}</p>
<p>}</p>
<p><strong>if</strong> (postData == <strong>null</strong>) {</p>
<p>conn.setRequestMethod(HttpConnection.<em>GET</em>);</p>
<p>} <strong>else</strong> {</p>
<p>conn.setRequestMethod(HttpConnection.<em>POST</em>);</p>
<p>conn.setRequestProperty(</p>
<p>HttpProtocolConstants.<em>HEADER_CONTENT_LENGTH</em>,</p>
<p>String.<em>valueOf</em>(postData.length));</p>
<p>out = conn.openOutputStream();</p>
<p>out.write(postData);</p>
<p>}</p>
<p>} <strong>catch</strong> (IOException e1) {</p>
<p>} <strong>finally</strong> {</p>
<p><strong>if</strong> (out != <strong>null</strong>) {</p>
<p><strong>try</strong> {</p>
<p>out.close();</p>
<p>} <strong>catch</strong> (IOException e2) {</p>
<p>}</p>
<p>}</p>
<p>}</p>
<p><strong>return</strong> conn;</p>
<p>}</p>
<p>}</p>
<p>Các bài liên quan:<br />
<a href="http://mobilesprogramming.wordpress.com/2010/11/09/blackberry-browser-api-ph%E1%BA%A7n-1/" target="_self"> Blackberry Browser API &#8211; Phần 1</a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mobilesprogramming.wordpress.com/733/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mobilesprogramming.wordpress.com/733/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mobilesprogramming.wordpress.com/733/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mobilesprogramming.wordpress.com/733/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/mobilesprogramming.wordpress.com/733/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/mobilesprogramming.wordpress.com/733/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/mobilesprogramming.wordpress.com/733/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/mobilesprogramming.wordpress.com/733/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mobilesprogramming.wordpress.com/733/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mobilesprogramming.wordpress.com/733/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mobilesprogramming.wordpress.com/733/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mobilesprogramming.wordpress.com/733/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mobilesprogramming.wordpress.com/733/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mobilesprogramming.wordpress.com/733/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mobilesprogramming.wordpress.com&amp;blog=11410337&amp;post=733&amp;subd=mobilesprogramming&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mobilesprogramming.wordpress.com/2010/11/15/blackberry-browser-api-ph%e1%ba%a7n-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/992f5fba26e8af9ebb4a25d922f208c6?s=96&#38;d=&#38;r=G" medium="image">
			<media:title type="html">mobilesprogramming</media:title>
		</media:content>
	</item>
		<item>
		<title>Blackberry Browser API &#8211; Phần 1</title>
		<link>http://mobilesprogramming.wordpress.com/2010/11/09/blackberry-browser-api-ph%e1%ba%a7n-1/</link>
		<comments>http://mobilesprogramming.wordpress.com/2010/11/09/blackberry-browser-api-ph%e1%ba%a7n-1/#comments</comments>
		<pubDate>Tue, 09 Nov 2010 14:40:02 +0000</pubDate>
		<dc:creator>mobilesprogramming</dc:creator>
				<category><![CDATA[BB Tutorial]]></category>
		<category><![CDATA[Blackberry]]></category>
		<category><![CDATA[basic-BB]]></category>

		<guid isPermaLink="false">http://mobilesprogramming.wordpress.com/?p=729</guid>
		<description><![CDATA[I.Browser API Package Description net.rim.blackberry.api.browser Cho phép ứng dụng hiển thị nội dung trên Web, bao gồm các kiểu image được hỗ trợ, các trang html và wml. Nó cũng cho phép ứng dụng cung cấp một referer, HTTP header và post dữ liệu trong HTTP request net.rim.blackberry.api.browser.field Cho phép ứng dụng lấy nội dung [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mobilesprogramming.wordpress.com&amp;blog=11410337&amp;post=729&amp;subd=mobilesprogramming&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<h2>I.Browser API</h2>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="295" valign="top">Package</td>
<td width="295" valign="top">Description</td>
</tr>
<tr>
<td width="295" valign="top">net.rim.blackberry.api.browser</td>
<td width="295" valign="top">Cho phép ứng dụng hiển thị nội dung trên Web, bao   gồm các kiểu image được hỗ trợ, các trang html và wml. Nó cũng cho   phép ứng dụng cung cấp một referer, HTTP header và post dữ liệu trong   HTTP request</td>
</tr>
<tr>
<td width="295" valign="top">net.rim.blackberry.api.browser.field</td>
<td width="295" valign="top">Cho phép ứng dụng lấy nội dung Web để hiển thị   trong browser field, được include trong giao diện người dùng, đồng thời   cho phép cấu hình sự xuất hiện của browser field</td>
</tr>
<tr>
<td width="295" valign="top">net.rim.blackberry.api.browser.plugin</td>
<td width="295" valign="top">Cho phép ứng dụng hỗ trợ thêm các kiểu định dạng   khác, bằng cách đăng ký như là một rendering provider cho một kiểu   MIME khi thiết bị Blackberry bắt đầu, tất cả các phiên trình duyệt   tiếp theo sẽ hỗ trợ các kiểu MIME bổ xung đó.</td>
</tr>
</tbody>
</table>
<h2>II.Hiểu Thị Nội Dung Web Trên Browser</h2>
<h3>1.Nhận một Browser session</h3>
<p>Để nhận một đối tượng BrowserSession mặc định, gọi phương thức tĩnh Browser.getDefaultSession(). Đối tượng  này cho phép bạn truy cập vào browser đang chạy trên thiết bị.</p>
<p><strong>Lưu ý</strong> Việc nhận một default session sẽ override các session đang mở trong thiết bị Blackberry.</p>
<p>Để nhận một session khác, bạn chỉ cần gọi phương thức getSession(). Phương thức này lấy một bản ghi cầu hình dịch vụ trình duyệt theo ID duy nhất của nó(UID).<span id="more-729"></span></p>
<h3>2.Yêu cầu một Web page</h3>
<p>Để yêu cầu một web page, gọi phương thức BrowserSession.displayPage(). Ví dụ dưới đây sử dụng các phiên bản của displayPage() mà chỉ chấp nhận một URL. Để xác định một referrer, HTTP header, và post dữ liệu, sử dụng phiên bản chấp nhận các đối số bổ sung này.</p>
<p>Ví dụ 1:</p>
<p>private MenuItem browserItem = new MenuItem(_resources.getString(MENUITEM_BROWSER), 110, 12) {</p>
<p>public void run() {</p>
<p>synchronized(store) {</p>
<p>String websiteUrl = websitefield.getText();</p>
<p>if (websiteUrl.length == 0) {</p>
<p>Dialog.alert(_resources.getString(ALERT_NO_WEBSITE));</p>
<p>} else {</p>
<p>BrowserSession visit = Browser.getDefaultSession();</p>
<p>visit.displayPage(websiteUrl);</p>
<p>}</p>
<p>}</p>
<p>}</p>
<p>};</p>
<h2>III.Hiển Thị Nội Dung Web Trong Một Browser Field</h2>
<p>Để hiển thị nội dung web trong một browser field, sử dụng gọi net.rim.device.api.browser.field. Thư viện trình diễn browser xử lý việc rendering nội dung web cho field và sau đó trả về một BrowserField -  đây là field mà nội dung web được rendering vào ứng dụng để hiển thị.</p>
<p><strong> </strong></p>
<p><strong>Lưu ý</strong> Phiên làm việc đã được sử dụng để mở browser field phụ thuộc vào phiên làm việc mặc định của browser trên thiết bị Blackberry.</p>
<p>Giao diện RenderingApplication định nghĩa các chức năng gọi lại (callback) một session rendering để hỗ trợ xử lý các tài nguyên URL. Việc cài đặt các phương thức trong RenderingApplication nhằm hiển thị nội dung web trong một browser field.</p>
<h3>1.Tạo một thread riêng biệt cho quá trình rendering</h3>
<p>Để tránh làm cho ứng dụng bị treo trong khi ứng dụng nhận và hiển thị browser field, bạn nên thực hiện các hành động đó trong một thread riêng biệt.</p>
<p>Ví dụ 2: Tạo một thread riêng biệt</p>
<p>class CreationThread extends Thread {</p>
<p>BrowserFieldHandlerApplication _callBackApplication;</p>
<p>BasicRenderingApplication  _renderingApplication;</p>
<p>public CreationThread(BrowserFieldHandlerApplication callBackApplication) {</p>
<p>_callBackApplication = callBackApplication;</p>
<p>}</p>
<p>public void run() {</p>
<p>_renderingApplication = new BasicRenderingApplication(_callBackApplication);</p>
<p>BrowserField field = _renderingApplication.getBrowserField(&#8220;www.blackberry.com&#8221;);</p>
<p>_callBackApplication.displayBrowserField(field);</p>
<p>}</p>
<p>}</p>
<h3>2.Thiết lập các tùy chọn Rendering</h3>
<p>Override phương thức getRenderingOptions() để thiết lập các tùy chọn, nếu bạn không override phương thức này, các tùy chọn rendering mặc định sẽ được sử dụng.</p>
<h3>3.Xử lý sự kiện</h3>
<p>Cài đặt phương thức eventOccured() để xử lý các sự kiện, như là một URL request.</p>
<p>Ví dụ 3:</p>
<p>public Object eventOccurred(Event event) {</p>
<p>int eventId = event.getUID();</p>
<p>switch (eventId) {</p>
<p>case Event.EVENT_URL_REQUESTED : {</p>
<p>UrlRequestedEvent e = (UrlRequestedEvent) event;</p>
<p>// This is a regular request.</p>
<p>String absoluteUrl = e.getURL();</p>
<p>HttpConnection conn = null;</p>
<p>OutputStream out = null;</p>
<p>try {</p>
<p>conn = (HttpConnection) Connector.open(absoluteUrl);</p>
<p>FormData postData = e.getPostData();</p>
<p>if (postData == null) {</p>
<p>conn.setRequestMethod(HttpConnection.GET);</p>
<p>} else {</p>
<p>conn.setRequestMethod(HttpConnection.POST);</p>
<p>byte[] postBytes = postData.getBytes();</p>
<p>conn.setRequestProperty(</p>
<p>HttpProtocolConstants.HEADER_CONTENT_LENGTH,</p>
<p>String.valueOf(postBytes.length));</p>
<p>if (conn.getRequestProperty(</p>
<p>HttpProtocolConstants.HEADER_CONTENT_TYPE) == null) {</p>
<p>conn.setRequestProperty(</p>
<p>HttpProtocolConstants.HEADER_CONTENT_TYPE,</p>
<p>postData.getContentType());</p>
<p>}</p>
<p>out = conn.openOutputStream();</p>
<p>out.write(postBytes);</p>
<p>}</p>
<p>HttpHeaders requestHeaders = e.getHeaders();</p>
<p>if (requestHeaders != null) {</p>
<p>/* From http://www.w3.org/Protocols/rfc2616/rfc2616-</p>
<p>sec15.html#sec15.1.354</p>
<p>&#8230;</p>
<p>Clients SHOULD NOT include a Referer header field in a</p>
<p>(non-secure) HTTP request if the referring page was</p>
<p>transferred with a secure protocol.*/</p>
<p>String referer = requestHeaders.getPropertyValue(&#8220;referer&#8221;);</p>
<p>boolean sendReferrer = true;</p>
<p>if (referer != null &amp;&amp; referer.startsWith(&#8220;https:&#8221;) &amp;&amp; !absoluteUrl.startsWith(&#8220;https:&#8221;)) {</p>
<p>sendReferrer = false;</p>
<p>}</p>
<p>int size = requestHeaders.size();</p>
<p>for (int i = 0; i &lt; size; i++) {</p>
<p>String header = requestHeaders.getPropertyKey(i);</p>
<p>// Remove refer header if needed.</p>
<p>if ( !sendReferrer &amp;&amp; header.equals(&#8220;referer&#8221;)) {</p>
<p>equestHeaders.removeProperty(i);</p>
<p>continue;</p>
<p>}</p>
<p>conn.setRequestProperty( header,</p>
<p>requestHeaders.getPropertyValue( i ) );</p>
<p>}</p>
<p>}</p>
<p>} catch (IOException e1) {</p>
<p>} finally {</p>
<p>if (out != null) {</p>
<p>try {</p>
<p>out.close();</p>
<p>} catch (IOException e2) {}</p>
<p>}</p>
<p>}</p>
<p>BrowserField browserField = getBrowserField(conn, e);</p>
<p>_callbackApplication.displayBrowserField(browserField);</p>
<p>break;</p>
<p>}</p>
<p>case Event.EVENT_BROWSER_FIELD_CHANGED : {</p>
<p>// Browser field title might have changed. Update title.</p>
<p>break;</p>
<p>}</p>
<p>case Event.EVENT_REDIRECT : {</p>
<p>RedirectEvent e = (RedirectEvent) event;</p>
<p>switch (e.getType()) {</p>
<p>case RedirectEvent.TYPE_SINGLE_FRAME_REDIRECT :</p>
<p>// Show redirect message.</p>
<p>Application.getApplication().invokeAndWait(new Runnable() {</p>
<p>public void run() {</p>
<p>Status.show(&#8220;&#8221;);</p>
<p>}</p>
<p>});</p>
<p>break;</p>
<p>case RedirectEvent.TYPE_JAVASCRIPT :</p>
<p>case RedirectEvent.TYPE_META :</p>
<p>case RedirectEvent.TYPE_300_REDIRECT :</p>
<p>}</p>
<p>String absoluteUrl = e.getLocation();</p>
<p>HttpConnection conn = null;</p>
<p>try {</p>
<p>conn = (HttpConnection) Connector.open(absoluteUrl);</p>
<p>} catch (IOException e1) {</p>
<p>}</p>
<p>BrowserField browserField = getBrowserField(conn,</p>
<p>e.getOriginalEvent());</p>
<p>_callbackApplication.displayBrowserField(browserField);</p>
<p>break;</p>
<p>}</p>
<p>case Event.EVENT_CLOSE :</p>
<p>// Close the appication.</p>
<p>break;</p>
<p>case Event.EVENT_SET_HEADER :// no cache support</p>
<p>case Event.EVENT_SET_HTTP_COOKIE :   // no cookie support</p>
<p>case Event.EVENT_HISTORY :   // no history support</p>
<p>case Event.EVENT_LOADING_IMAGES :// no progress bar is supported</p>
<p>case Event.EVENT_EXECUTING_SCRIPT :  // no progress bar is supported</p>
<p>case Event.EVENT_FULL_WINDOW :   // no full window support</p>
<p>case Event.EVENT_STOP :  // no stop loading support</p>
<p>default :</p>
<p>}</p>
<p>return null;</p>
<p>}</p>
<h3>4.Nhận nội dung browser để rendering</h3>
<p>Cài đặt phương thức getBrowserField() để nhận nội dung browser để rendering. Phương thức getBrowserField() gọi phương thức RenderingSession.getBrowserField() để nhận một browser field, ứng dụng không thể khởi tạo browser field một cách trực tiếp.</p>
<p>Ví dụ 4:</p>
<p>public BrowserField getBrowserField (String absoluteUrl) {</p>
<p>HttpConnection conn = null;</p>
<p>try {</p>
<p>conn = (HttpConnection) Connector.open(absoluteUrl);</p>
<p>// Set transcode to true.</p>
<p>conn.setRequestProperty( &#8220;x-rim-transcode-content&#8221;, &#8220;*/*&#8221; );</p>
<p>} catch (IOException e1) {</p>
<p>}</p>
<p>return getBrowserField(conn, null);</p>
<p>}</p>
<p>private BrowserField getBrowserField(HttpConnection conn, Event e) {</p>
<p>BrowserField field = null;</p>
<p>try {</p>
<p>field = _renderingSession.getBrowserField(conn, this, e);</p>
<p>} catch (RenderingException re) {</p>
<p>return null;</p>
<p>}</p>
<p>// Add to the event queue a thread that invokes finishLoading().</p>
<p>Application.getApplication().invokeLater(new RenderingThread(field));</p>
<p>return field;</p>
<p>}</p>
<h3>5.Rendering browser field</h3>
<p>Gọi phương thức finishLoading(). Trong ví dụ trên, BrowserField.getBrowserField() chạy phương thức finishLoading() bằng cách thêm một thread mới vào event queue của ứng dụng.</p>
<p><strong>Lưu ý</strong> Các file HTML sẽ hiển thị một blank field cho đến khi bạn gọi phương thức BrowserField.finishLoading(). Các file WML hay các image có thể được load trước khi phương thức này được gọi. Chạy phương thức finishLoading() trên một thread mới để UI không bị khóa.</p>
<p>Ví dụ 5:</p>
<p>class RenderingThread implements Runnable {</p>
<p>BrowserField _browserField;</p>
<p>RenderingThread(BrowserField field) {</p>
<p>_browserField = field;</p>
<p>}</p>
<p>public void run() {</p>
<p>try {</p>
<p>_browserField.finishLoading();</p>
<p>} catch (RenderingException e) {</p>
<p>// Handle exception.</p>
<p>}</p>
<p>}</p>
<p>}</p>
<h3>6.Hiển thị BrowserField</h3>
<p>Cài đặt phương thức displayBrowserField() bằng cách xóa nội dung cũ và thêm browser field vào màn hình.</p>
<p>Ví dụ 6:</p>
<p>public void displayBrowserField(BrowserField browserField) {</p>
<p>synchronized (Application.getEventLock()) {</p>
<p>_vfm.deleteAll();</p>
<p>_vfm.add(browserField);</p>
<p>}</p>
<p>}</p>
<p>Các bài liên quan:<br />
<a href="http://mobilesprogramming.wordpress.com/2010/11/15/blackberry-browser-api-ph%E1%BA%A7n-2/" target="_self">Blackberry Bbrowser API &#8211; Phần 2</a></p>
<br />Filed under: <a href='http://mobilesprogramming.wordpress.com/category/blackberry/bb-tutorial/'>BB Tutorial</a>, <a href='http://mobilesprogramming.wordpress.com/category/blackberry/'>Blackberry</a> Tagged: <a href='http://mobilesprogramming.wordpress.com/tag/basic-bb/'>basic-BB</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mobilesprogramming.wordpress.com/729/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mobilesprogramming.wordpress.com/729/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mobilesprogramming.wordpress.com/729/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mobilesprogramming.wordpress.com/729/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/mobilesprogramming.wordpress.com/729/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/mobilesprogramming.wordpress.com/729/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/mobilesprogramming.wordpress.com/729/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/mobilesprogramming.wordpress.com/729/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mobilesprogramming.wordpress.com/729/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mobilesprogramming.wordpress.com/729/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mobilesprogramming.wordpress.com/729/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mobilesprogramming.wordpress.com/729/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mobilesprogramming.wordpress.com/729/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mobilesprogramming.wordpress.com/729/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mobilesprogramming.wordpress.com&amp;blog=11410337&amp;post=729&amp;subd=mobilesprogramming&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mobilesprogramming.wordpress.com/2010/11/09/blackberry-browser-api-ph%e1%ba%a7n-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/992f5fba26e8af9ebb4a25d922f208c6?s=96&#38;d=&#38;r=G" medium="image">
			<media:title type="html">mobilesprogramming</media:title>
		</media:content>
	</item>
		<item>
		<title>Phát triển game trên Blackberry</title>
		<link>http://mobilesprogramming.wordpress.com/2010/10/03/phat-tri%e1%bb%83n-game-tren-blackberry/</link>
		<comments>http://mobilesprogramming.wordpress.com/2010/10/03/phat-tri%e1%bb%83n-game-tren-blackberry/#comments</comments>
		<pubDate>Sun, 03 Oct 2010 13:08:21 +0000</pubDate>
		<dc:creator>mobilesprogramming</dc:creator>
				<category><![CDATA[Code Blackberry]]></category>
		<category><![CDATA[Code Example]]></category>
		<category><![CDATA[Open Sources]]></category>
		<category><![CDATA[OS Game]]></category>
		<category><![CDATA[game]]></category>

		<guid isPermaLink="false">http://mobilesprogramming.wordpress.com/?p=724</guid>
		<description><![CDATA[Trong bài này, tôi xin giới thiệu các bạn một game &#8220;space fighter&#8221;. Nó có hướng dẫn rất đầy đủ, bạn có thể tham khảo tại: http://www.toniwestbrook.com/archives/69. Giao diện của nó như sau: Chúc các bạn thành công! Filed under: Code Blackberry, Code Example, Open Sources, OS Game Tagged: Code Blackberry, game<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mobilesprogramming.wordpress.com&amp;blog=11410337&amp;post=724&amp;subd=mobilesprogramming&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Trong bài này, tôi xin giới thiệu các bạn một game &#8220;space fighter&#8221;. Nó có hướng dẫn rất đầy đủ, bạn có thể tham khảo tại: <a href="http://www.toniwestbrook.com/archives/69" target="_blank">http://www.toniwestbrook.com/archives/69</a>. Giao diện của nó như sau:</p>
<p><a href="http://mobilesprogramming.files.wordpress.com/2010/10/product-galacticblast1.jpg"><img class="aligncenter size-full wp-image-725" title="product-galacticblast1" src="http://mobilesprogramming.files.wordpress.com/2010/10/product-galacticblast1.jpg?w=570" alt=""   /></a><a href="http://mobilesprogramming.files.wordpress.com/2010/10/product-galacticblast2.jpg"><img class="aligncenter size-full wp-image-726" title="product-galacticblast2" src="http://mobilesprogramming.files.wordpress.com/2010/10/product-galacticblast2.jpg?w=570" alt=""   /></a></p>
<p>Chúc các bạn thành công!</p>
<br />Filed under: <a href='http://mobilesprogramming.wordpress.com/category/code-example/code-blackberry/'>Code Blackberry</a>, <a href='http://mobilesprogramming.wordpress.com/category/code-example/'>Code Example</a>, <a href='http://mobilesprogramming.wordpress.com/category/open-sources/'>Open Sources</a>, <a href='http://mobilesprogramming.wordpress.com/category/open-sources/os-game/'>OS Game</a> Tagged: <a href='http://mobilesprogramming.wordpress.com/tag/code-blackberry/'>Code Blackberry</a>, <a href='http://mobilesprogramming.wordpress.com/tag/game/'>game</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mobilesprogramming.wordpress.com/724/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mobilesprogramming.wordpress.com/724/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mobilesprogramming.wordpress.com/724/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mobilesprogramming.wordpress.com/724/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/mobilesprogramming.wordpress.com/724/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/mobilesprogramming.wordpress.com/724/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/mobilesprogramming.wordpress.com/724/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/mobilesprogramming.wordpress.com/724/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mobilesprogramming.wordpress.com/724/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mobilesprogramming.wordpress.com/724/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mobilesprogramming.wordpress.com/724/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mobilesprogramming.wordpress.com/724/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mobilesprogramming.wordpress.com/724/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mobilesprogramming.wordpress.com/724/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mobilesprogramming.wordpress.com&amp;blog=11410337&amp;post=724&amp;subd=mobilesprogramming&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mobilesprogramming.wordpress.com/2010/10/03/phat-tri%e1%bb%83n-game-tren-blackberry/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/992f5fba26e8af9ebb4a25d922f208c6?s=96&#38;d=&#38;r=G" medium="image">
			<media:title type="html">mobilesprogramming</media:title>
		</media:content>

		<media:content url="http://mobilesprogramming.files.wordpress.com/2010/10/product-galacticblast1.jpg" medium="image">
			<media:title type="html">product-galacticblast1</media:title>
		</media:content>

		<media:content url="http://mobilesprogramming.files.wordpress.com/2010/10/product-galacticblast2.jpg" medium="image">
			<media:title type="html">product-galacticblast2</media:title>
		</media:content>
	</item>
	</channel>
</rss>
