#AndroidStudio ตอนที่ 11 แอพสำหรับ Tablet(Wide)/Smartphone(Narrow) มีตัวเลือกรายการด้านซ้าย รายละเอียดด้านขวา ถ้าจอกว้างพอ

#AndroidStudio ตอนที่ 11 แอพสำหรับ Tablet(Wide)/Smartphone(Narrow) มีตัวเลือกรายการด้านซ้าย รายละเอียดด้านขวา ถ้าจอกว้างพอ

<introduction>
อารัมภบท
การเขียน App สักตัว ที่ต้องการให้มี ซีกซ้าย (Left Pane) เป็นรายการตัวเลือก และซีกขวา (Right Pane) เป็นรายละเอียดหลังคลิ๊กไปที่รายการ ทาง Android เข้าใจเรา ได้เตรียม Template (อ่านได้จาก Add Code from a Template ) มาให้เราเลือก 12 แบบ พบว่า Main/Detail Flow เป็นแบบที่แบ่งจอภาพเป็น Two section สำหรับจอแบบ Wide screen แต่จะหดให้ทำงานกับ One section หากเป็น Narrow screen ซึ่งเค้ากำหนดว่า Wide screen คือ 900dp และผมใช้ Smartphone ก็จะไม่มีโอกาสได้เห็นแบบ 2 section แต่ใน code หากปรับชื่อ folder เป็น 600 dp ก็ทำให้ app รองรับการแสดงผลแบบ Main/Detail Flow บน Smartphone ได้

การเรียนรู้การทำงานของ Template นี้ ก็ต้องหา Activity เข้าไปใส่ แล้วค่อยแกะค่อยไซร้ไป ไม่งั้นจะให้พิมพ์ Hello world! กันทุก Project ก็คงจะจืดแยเลย จึงใส่ตัวเลือกเข้าไป 6 รายการ คือ API Level, Security_patch, width & height, IP Address, Date and Time และ Webview เมื่อต้องทำให้แต่ละกิจกรรมทำงานได้ พบปัญหาว่า บางกิจกรรมใช้ method ใน Dummycontent.java ไม่ได้ แก้ไขโดยไปใส่ใน Activity หลัก ซึ่งปัญหาที่พบบ่อยมี 2 สาเหตุ คือ 1) ฟังก์ชันนั้นต้องเรียกใช้ Context ของ Activity แต่ไม่มีให้ใช้ในคลาสนั้น 2) การเรียกใช้ฟังก์ชัน ไม่สามารถใช้ได้หากอยู่ใน method แบบ static จึงต้องย้ายงานไปทำใน Activity หลัก อาทิ MainActivity.java แล้วเก็บเป็นตัวแปรให้อ้างอิงได้ เมื่อ Dummy ต้องการใช้ ก็อ้างอิงเป็นวัตถุใน Dummy แล้วนึกไปใช้ได้ แต่ Project นี้มี Activity หลักอยู่ใน ItemListActivity.java

ระหว่างพัฒนา และทดสอบ ได้พบกับคำว่า Unfortunately บ่อยเลย เพราะการใช้ method ในที่ห้ามใช้ ระบบปฏิบัติการไม่อาจดำเนินการตามที่คาดไว้ แต่ Build APK ผ่าน ไม่มีปัญหานะครับ ปัญหาไปเกิดตอนประมวลผล ก็ต้องแก้ไขกันไป เพราะเงื่อนไขเยอะมาก หากันจนเจอ หรือหากันให้เจอ เมื่อต้องเจอปัญหาในแต่ละครั้ง

สรุปกระบวนการได้ 13 ขั้นตอน ประกอบด้วย 1) สร้าง Project เลือก Template แบบ Master/Detail Flow 2) ทำให้ item ใน list มีกิจกรรม 3) เพิ่มเกิจกรรมให้ตัวเลือกแต่ละตัว ใน DummyContent.java 4) การได้ ipaddress ต้องปรับ AndroidManifest.xml 5) สร้าง WebView ชื่อ aboutus.xml รับ HTML Tag 6) การเพิ่ม layout แบบ WebView แทน TextView จำนวน 1 ตัวเลือก 7) การหาขนาด Width และ Height ของจอภาพ 8) การหาค่า IP Address 9) การหาวันเวลาของเครื่อง 10) การหาเลขรุ่น API ของ Android ที่มีในโทรศัพท์แต่ละเครื่อง 11) การส่งค่าเข้าตัวแปรแบบตัวเลข และตัวอักษรใน string 12) การอ้างอิงชื่อ id, string, layout, drawable แบบอ้างอิงด้วยตัวแปร 13) การติดตั้ง Android 7.1 บน VirtualBox


ปล. แฟ้ม Project ผมบีบไว้ และแชร์ให้ Download ทั้ง .rar และ .apk ไปทดสอบกัน
ที่ http://www.thaiall.com/android (ผ่าน 4shared.com)

</introduction>
<definition>
นิยามศัพท์

  1. Template คือ แบบฟอร์มที่ยังไม่ได้ใส่เนื้อหา แต่มีเค้าโครง (Layout) หรือกิจกรรม (Activity) ที่จำเป็นมาให้แล้ว ซึ่ง Android มีให้เลือก 12 แบบ สามารถนำมาปรับแต่งเสมือนกับโครงงานที่สร้างขึ้นใหม่ แต่เทมเพลตจะช่วยล่นระยะเวลาในการพัฒนาระบบในระยะแรกให้สั้นลง แทนการเริ่มต้นจาก 0 หรือการนับ 1 ใหม่
  2. Unfortunately คือ ปัญหาที่ไม่คาดหวัง แต่มาปรากฎบนหน้าจออุปกรณ์ของเราได้ ในกรณีที่เกิดขึ้นจากการติดตั้งและใช้แอพที่ยังอยู่ในระหว่างพัฒนา ก็ลบแอพ (Uninstall) แล้วกลับไปไล่ดูเงือนไขของ command หรือ method หรือ class ที่เรียกใช้ อาจใช้บาง method ที่ใหม่เกินกว่า API ในเครื่องจะรองรับ หรือเก่าเกินไป หรือความไม่เข้ากับของการใช้คำสั่ง แต่ถ้าเป็น App ที่พัฒนา และใช้งานมาแล้วระยะหนึ่ง มีคำแนะนำให้ Clear cache and data หรือ ลบ App แล้วลงใหม่ หรือ Factory reset เป็นต้น

</definition>

กำลังเล่าเรื่อง การใช้โปรแกรม Android Studio สู่เพื่อนนักพัฒนา ผ่าน Blog

<process>
กระบวนการในการพัฒนา APP
เพื่อให้ได้แอพที่แสดงผล Main กับ Detail แยกกัน และแสดงผลต่างกันกับอุปกรณ์แบบ Wide screen และ Narrow screen
มีขั้นตอน ดังนี้

1. สร้าง Project เลือก Template แบบ Master/Detail Flow
ตั้งชื่อให้ project ว่า mainanddetail
เป็นตัวอย่างโครงงานที่น่าสนใจ สามารถนำมาปรับเป็นแอพที่ใช้งานจริงได้
หากใช้กับ Narrow screen จะมีเพียง one screen
หากใช้กับ Wide screen จะแบ่งการทำงานเป็น 2 Section
คือ ซีกซ้ายสำหรับรายการเมนู (Option List) และซีกขวาสำหรับรายละเอียดข้อมูล (Detail)
มีแฟ้มน่าสนใจ 9 แฟ้มที่จะเล่าสู่กันฟัง ดังนี้
https://inducesmile.com/android/android-fragment-masterdetail-flow-tutorial-in-android-studio/

1.1 สำรวจแฟ้ม AndroidManifest.xml
พบว่าใน <application> ได้กำหนด activity ไว้ 2 section
เพื่อเรียก .ItemListActivity และเรียก .ItemDetailActivity
โดย .ItemDetailActivity ที่มี parent คือ .ItemListActivity”
แสดงว่า 1) ItemListActivity.java คือ Activity หลัก
และทำงานคู่กับ 2) ItemDetailActivity.java อย่างที่เรียกว่าแยกกันไม่ออกทีเดียว
จะเห็นว่างานเริ่มจากการเรียก 2 Activity แต่จะแสดง Layout จากทั้ง 2 หรือไม่
ขึ้นกับว่าจอภาพที่ใช้เป็นแบบ Wide หรือ Narrow

1.2 สำรวจ Activity ที่ 1 แฟ้ม ItemListActivity.java
พบว่าใน oncreate ได้สั่ง setContentView(R.layout.activity_item_list);
ซึ่งจะไปเรียกให้ Layout แบบ CoordinatorLayout ที่มีอะไรหลายอย่างทำงานร่วมกัน
Activity นี้ควบคุมงานทางด้านซ้าย (Left Pane) คือ รายการตัวเลือก

1.3 สำรวจ Layout ที่ 1 แฟ้ม activity_item_list.xml
โครงร่างหลักสำหรับการวางวัตถุในด้านซ้าย (Left Pane)
มี Root Layout เป็น CoordinatorLayout
ที่ใช้ AppBarLayout กับ FloatingActionButton
ซึ่งพบได้ใน Template แบบ Basic Activity ที่อธิบายในตอนที่ 9 ข้อ 1
แล้วเรียก Layout อื่นให้ทำหน้าที่แสดงตัวเลือกผ่าน FrameLayout และ include
พบว่ามี Layout structure ดังนี้

<CoordinatorLayout>
 <AppBarLayout>
 <Toolbar />
 </AppBarLayout>
 <FrameLayout>
 <include layout="@layout/item_list" />
 </FrameLayout>
 <FloatingActionButton />
 </CoordinatorLayout>

1.4 สำรวจ Layout ที่ 2 แฟ้ม activity_item_detail.xml
โครงร่างหลักสำหรับการวางรายละเอียดในด้านขวา (Right Pane)
หรือเป็น Full Parent หากทำงานบน Narrow Screen
มี Root Layout เป็น CoordinatorLayout เช่นกัน
จะทำหน้าที่แสดงข้อมูลด้านขวาสำหรับจอภาพที่กว้างไม่น้อยกว่า 900 dp
แต่จะเป็น full screen แทน activity_item_list.xml หากน้อยกว่า 900 dp
– การแสดงเนื้อหามีทำงานกับ fragment แล้วนำไปรวมกันใน Layout
ซึ่งมีความสัมพันธ์ระหว่างแฟ้ม java จำนวน 3 แฟ้ม
– การแสดงข้อมูลมีกิจกรรมใน 1) ItemDetailActivity.java ทำหน้าที่รับอะไรจากใครเข้าไป
แล้วพบการเชื่อมกับ 2) ItemDetailFragment.java
ด้วยคำสั่ง arguments.putString(ItemDetailFragment.ARG_ITEM_ID, ..
และ .add(R.id.item_detail_container, fragment) ..
ซึ่ง item_detail_container อยู่ใน Layout activity_item_detail.xml
– หากเข้าไปดูใน ItemDetailFragment.java
พบว่า มีการเชื่อมกับ ARG_ITEM_ID กับ 3) DummyContent.java อีกทีหนึ่ง
มีรายละเอียดที่น่าสนใจอีกมากมายใน DummyContent.java

พบว่ามี Layout structure ดังนี้

<CoordinatorLayout>
 <AppBarLayout>
 <CollapsingToolbarLayout>
 <Toolbar />
 </CollapsingToolbarLayout>
 </AppBarLayout>
 <NestedScrollView android:id="@+id/item_detail_container" />
 <FloatingActionButton />
 </CoordinatorLayout>

1.5 สำรวจ Layout ที่ 3 แฟ้ม item_detail.xml
โครงร่างย่อยสำหรับแสดงเนื้อหาโดยตรง และรับข้อมูลแบบ TextView
ทำงานสำหรับด้านขวา (Right Pane) เท่านั้น
พบว่า TextView ถูกเชื่อมข้อมูลกับ DummyContent.java ผ่านคำสั่งใน ItemDetailFragment.java
คือ ((TextView) rootView.findViewById(R.id.item_detail)).setText(mItem.details)
เมื่อเห็นการทำงานของ Layout นี้ จึงนำไปปรับใช้เป็น WebView ในตอนท้ายของบทความนี้

พบว่ามี Layout structure ดังนี้

<TextView id="@+id/item_detail" /> (แฟ้มนี้มี Tag เดียว)

1.6 สำรวจ Layout ที่ 4 แฟ้ม item_list.xml
โครงร่างย่อยสำหรับรายการตัวเลือก ทำงานด้านซ้าย (Left Pane) เท่านั้น
พบว่า findViewById(R.id.item_list) ถูกเชื่อมเข้า View ใน ItemListActivity.java
แล้วเชื่อมโยงระหว่าง RecycleView กับ DummyContent ผ่าน .setAdapter()
หน้าที่ของ item_list คือ แสดงหน่วยข้อมูล (item) ให้เลือกแบบรายการ (List)
พบว่ามี Layout structure ดังนี้

<RecyclerView id="@+id/item_list" /> (แฟ้มนี้มี Tag เดียว)

1.7 สำรวจ Layout ที่ 5 แฟ้ม item_list.xml (w900dp)
คล้ายกับ 1.6 แต่หากจอภาพเป็นแบบ Wide Screen
รองรับการแสดง FrameLayout ที่กว้าง 900 dp ได้ ก็จะมี 2 Pane
มีการตรวจสอบ และกำหนดค่าให้กับ mTwopane = true
ซึ่งพบใน ItemListActivity.java
หากปรับขนาดจาก 900 dp เหลือ 600 dp ก็จะแสดงผลบน Smartphone ของผมได้
จึงลดขนาดด้วยการ rename folder เป็น layout-w600dp
ผ่านการ Right Click เลือก [Show in Explorer] แล้วก็ rename folder ได้เลย
http://www.appstoremarketresearch.com/articles/android-tutorial-master-detail-flow/

พบว่ามี Layout structure ดังนี้

<LinearLayout>
 <RecyclerView id="@+id/item_list" />
 <FrameLayout id="@+id/item_detail_container" />
</LinearLayout>

1.8 สำรวจ Layout ที่ 6 แฟ้ม item_list_content.xml
โครงร่างย่อยสำหรับแสดงรายการตัวเลือกแต่ละรายการ
ปกติจะมีลำดับตัวเลือก และชื่อตัวเลือก ก็จะเป็นตาม Layout นั้น
ส่วนแฟ้มที่กำหนดขนาด (Dimension) คือ dimens.xml
หากเปลี่ยน <dimen name=”text_margin”> ก็จะมีผลต่อ Layout
ที่อ้างอิงผ่าน layout_margin=”@dimen/text_margin”

พบว่ามี Layout structure ดังนี้

<LinearLayout android:orientation="horizontal">
 <TextView />
 <TextView />
</LinearLayout>

2. ทำให้ item ใน list มีกิจกรรม
พบว่าแฟ้ม DummyContent.java ควบคุมการแสดงรายการตัวเลือก
และกิจกรรมหลังเลือกตัวเลือก
หากจะปรับเปลี่ยนจำนวนตัวเลือก หรือเปลี่ยนชื่อตัวเลือก
จาก 25 รายการเป็น 10 รายการ ก็สามารถทำได้
สามารถเปลี่ยน for ใน static เป็นดังนี้

มองหา
 private static final int COUNT = 25;
 static {
 for (int i = 1; i <= COUNT; i++) {
 addItem(createDummyItem(i));
เปลี่ยนเป็น
 private static final int COUNT = 5;
 static {
 addItem(new DummyItem("1","API Level",makeDetails(1)));
 addItem(new DummyItem("2","SECURITY_PATCH",makeDetails(2)));

3. เพิ่มเกิจกรรมให้ตัวเลือกแต่ละตัว ใน DummyContent.java

มองหา
 builder.append("Details about Item: ").append(position);
 for (int i = 0; i < position; i++) { .. }
 return builder.toString();
เปลี่ยนเป็น
 builder.append("Data ID : ").append(position);
 switch(position){
 case 1:
 builder.append("\nAPI Level = ")
 builder.append(String.valueOf(Build.VERSION.SDK_INT)); // 21
 return builder.toString();

4. การได้ ipaddress ต้องปรับ AndroidManifest.xml
โดยเพิ่ม 2 tag นี้ ก่อนเปิด tag <application>

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

มีตัวอย่างคำสั่งในข้อ 8

 

5. สร้าง WebView ชื่อ aboutus.xml รับ HTML Tag
สร้าง Layout ใหม่ให้มีเพียง WebView คล้ายกับ item_detail.xml
แล้วปรับให้การคลิ๊ปปุ่มบน FloatingActionButton ไปเรียก aboutus.xml
เลือกการเปลี่ยน include ใน activity_item_list.xml
ใช้วิธีการกำหนด ViewFlipper เคยเล่าในตอนที่ 10 ข้อ 1

5.1 ปรับแฟ้ม activity_item_list.xml
เพื่อสลับกันไปมาระหว่างการกดปุ่ม FloatingActionButton
คือเลือกระหว่างแสดง item_list กับ aboutus
หาก include item_list ใน wide screen จะมา 2 section
หาก include aboutus ใน wide screen จะมาเฉพาะ WebView

มองหา
 <include layout="@layout/item_list" />
เปลี่ยนเป็น
 <ViewFlipper
 android:id="@+id/view_flipper"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent">
 <include layout="@layout/item_list" />
 <include layout="@layout/aboutus" />
 </ViewFlipper>

https://developer.android.com/reference/android/webkit/WebView.html
https://www.mkyong.com/android/android-webview-example/

5.2 ปรับแฟ้ม ItemListActivity.java
ใน fab.setOnClickListener(new View.OnClickListener() { }
ซึ่งใช้ switch สนับกันสั่ง setDisplayedChild

เพิ่มคำสั่งต่อไปนี้

ViewFlipper vf = (ViewFlipper) findViewById(R.id.view_flipper);
 switch (vf.getDisplayedChild()) {
 case 0:
 vf.setDisplayedChild(1);
 WebView webView = (WebView) findViewById(R.id.webview);
 webView.getSettings().setJavaScriptEnabled(true);
 String mData = getString(R.string.mdata);
 //webView.loadData(mData, "text/html", null);
 webView.loadDataWithBaseURL("file:///android_res/drawable/",
 "<img src='test.jpg' />", "text/html", "utf-8", null);
 break;
 case 1: vf.setDisplayedChild(0); break; }

5.3 เปลี่ยนภาพปุ่ม
เลือก ic_menu_help ที่แสดงเครื่องหมาย ? บน FloatingActionButton
ด้วย app:srcCompat=”@android:drawable/ic_menu_help”

5.4 เขียน HTML แบบใช้ entity reference
คือการใช้ &lt; แทนเครื่องหมาย <

<string name="mdata">
 &lt;html>&lt;body>
 &lt;b>Hello world!&lt;/b>&lt;br/>
 &lt;center>&lt;img src="bridge.jpg" height=200 />&lt;/center>
 &lt;table width=100% bgcolor=yellow>&lt;tr>&lt;td>&lt;center>
 A bridge is in Lampang province, Thailand.
 &lt;/td>&lt;/tr>&lt;/table>
 &lt;/body>&lt;/html>
 </string>

6. การเพิ่ม layout แบบ WebView แทน TextView จำนวน 1 ตัวเลือก
พบว่า มีการส่ง R.layout.item_detail
เข้าไปใน rootView ใน ItemDetailFragment.java
ผ่านคำสั่ง rootView = inflater.inflate(R.layout.item_detail,..
ก็เพียงแต่เปลี่ยนจาก item_detail เป็น aboutus เท่านั้น
เปลี่ยนเป็น rootView = inflater.inflate(R.layout.aboutus,..
แล้วปรับแฟ้ม aboutus.xml ให้คล้าย item_detail.xml ที่มีเพียง Tag เดียว
เพื่อเข้าไปอยู่ใน rootView แล้วแสดงผลร่วมกับ appBarLayout ดังนี้

<WebView xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:id="@+id/webview"
 style="?android:attr/textAppearanceLarge"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:padding="16dp"
 android:textIsSelectable="true"
 tools:context="com.thaiall.www.mainanddetail.ItemDetailFragment" />

โดย rootView ใน ItemDetailFragment.java
จะถูกนำเข้า fragment แล้วรวมกับ container ใน ItemDetailActivity.java
ผ่านคำสั่ง getSupportFragmentManager().beginTransaction()
.add(R.id.item_detail_container, fragment)

7. การหาขนาด Width และ Height ของจอภาพ
ทำใน Activity หลักที่มี Context
แล้วเรียกค่าไปใช้ใน Dummy project ได้

การเรียกใช้ใน Dummy project

import com.thaiall.www.mainanddetail.ItemListActivity;
private static ItemListActivity item = new ItemListActivity();
builder.append(item.screenWidth);

ประกาศตัวแปรไว้ใต้ Class แบบ static

public static int screenHeight = 0;
 public static int screenWidth = 0;

คำสั่งสำหรับหาค่า Width กับ Height ใช้ใน Activity หลัก

// Width=720pixel Height=1280pixel
// DisplayMetrics displayMetrics = getResources().getDisplayMetrics(); 
DisplayMetrics displayMetrics = new DisplayMetrics();
WindowManager wm = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE); 
wm.getDefaultDisplay().getMetrics(displayMetrics);
screenHeight = displayMetrics.heightPixels;
screenWidth = displayMetrics.widthPixels;

8. การหาค่า IP Address

WifiManager wifiMan = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
 WifiInfo wifiInf = wifiMan.getConnectionInfo();
 int ipAddress = wifiInf.getIpAddress();
 ip = String.format("%d.%d.%d.%d", 
(ipAddress & 0xff),(ipAddress >> 8 & 0xff),
(ipAddress >> 16 & 0xff),(ipAddress >> 24 & 0xff));

9. การหาวันเวลาของเครื่อง

getDateTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Calendar.getInstance().getTime());

10. การหาเลขรุ่น API ของ Android ที่มีในโทรศัพท์แต่ละเครื่อง

builder.append(String.valueOf(Build.VERSION.SDK_INT)); 
// I-Mobile IQ II 21
builder.append(String.valueOf(Build.VERSION.RELEASE)); 
// 5.0 (Lollipop) or 4.4.2 (Kitkat)

11. การส่งค่าเข้าตัวแปรแบบตัวเลข และตัวอักษรใน string
ตัวอย่างนี้ไม่ได้อยู่ใน project ที่ทดสอบนี้ แต่ค้นมาแล้วอยากเล่าเก็บไว้
จะรับข้อมูลจาก 3 ตัวแปร ที่ผสมระหว่างตัวเลข และตัวอักษร
จึงจะทำให้ข้อมูลสมบูรณ์ ตัวอย่างนี้ตัวแปรจะมีลำดับที่เริ่มจาก 1
ส่งเข้าไปผ่าน method getResources และ getString

<string name="x1">a= %1$d and b= %2$s and c= %3$d</string>
int a = 1024;
String b = "ASCII";
int c = 65536;
String y = getResources().getString(R.string.x1, a, b, c);

12. การอ้างอิงชื่อ id, string, layout, drawable แบบอ้างอิงด้วยตัวแปร
ตัวอย่างนี้ไม่ได้อยู่ใน project ที่ทดสอบนี้ แต่ค้นมาแล้วอยากเล่าเก็บไว้
บางครั้ง มีข้อมูลจำนวนมากใน string หรือ drawable
แล้วต้องการอ้างอิงแบบเขียน code ให้สั้น
ไม่ใช่มี 100 ภาพ ก็เขียน 100 บรรทัด ก็มีเทคนิค หรือ algorithm อยู่ครับ

int n = 1;
String tv ="R.id.x" + n;
int id = getResources().getIdentifier(tv, "id", getPackageName());
TextView v1 = (TextView) findViewById(id);
v1.setText("new value");
// R.layout.v1
// getResources().getIdentifier("v" + 1, "layout", getPackageName());
// R.string.v2
// getResources().getIdentifier("v" + 2, "string", getPackageName());
// R.drawable.v3
// getResources().getIdentifier("v" + 3, "drawable", getPackageName());

13. การติดตั้ง Android 7.1 บน VirtualBox
เริ่มต้นจากการ Download แฟ้ม .iso สำหรับติดตั้ง Android
http://www.android-x86.org/download

มีขั้นตอน ดังนี้

– Installation
– Create/Modify Partitions
แบบนี้เป็นปัญหา Other และ Other/Unknown
แบบนี้ผ่านด้วยดี Windows และ Windows 32 Bits
แบบนี้ผ่านด้วยดี Ubuntu และ Ubuntu 32 Bits
– use GPT = no
– in partition 1
– write in bootable and primary and Quit
– select SDA1 and format in ext4
– install GRUB and /system
– select [run Android-x86]
– Let’s go
– Setup as new
– Checking for update
– Get connected
– Don’t use any network for setup
– continue and Next
– name=android
– Google services > Next
– Anything else? > ALL SET
– Home screen
– chrome + accept policy
– no signin
– click O > Home screen
– click up arrow
– click Terminal emulator
– $ifconfig = ip address 192.168.1.2

</process>

<website_guide>
+ http://benzneststudios.com/../context-android-overview/
+ https://developer.android.com/../string-resource.html
+ https://stackoverflow.com/..using-getresources-in-non-activity-class
+ https://stackoverflow.com/..get-context-on-android
+ https://stackoverflow.com/..use-getsystemservice-in-a-non-activity
+ https://stackoverflow.com/..get-screen-dimensions-in-pixels
+ https://stackoverflow.com/..get-screen-width-and-height
+ https://stackoverflow.com/..getwindowmanager-by-another-java
+ https://www.youtube.com/watch?v=hjY06ZmYl8U
</website_guide>

หมายเหตุ 
ถ้าสนใจติดตามเนื้อหาในบล็อกนี้ สามารถ subscribe ด้วย email ที่อยู่ข้างขวา หรือ click here

จัดการปัญหา Wifi กับ IPAD

static ip
static ip

เหตุเกิดจากการใช้ IPAD เกาะสัญญาณ Wifi แล้วได้ IP Address แต่ Login เข้าระบบไม่ได้ อาการคือ browser ค้างหลังกดปุ่ม Login การแก้ปัญหาทำโดยเพื่อนร่วมงานของผม คุณตุ้ย 1) ตรวจว่า IPAD ได้ IP Address หมายเลขอะไร 2) reserve IP Address กับ Mac Address  3) กำหนด User ให้กับ Static IP Address ต่อไป IPAD ของผู้ใช้ก็จะเข้าใช้ระบบ แล้วได้ IP และ User ทันที ถ้ามาจาก Mac Address เดิม

อีกปัญหาที่ยังไม่ได้แก้ไข คือ IPAD ของผู้ใช้ไม่มี Flash Player ซึ่งปัญหานี้ทำให้ counter แบบ flash หรือ e-book แบบ flash ไม่แสดงผล หรือหายไปเฉย ๆ จากการทดสอบกับ thaiall.com/e-book หรือระบบบันทึกสถิติของ histats.com ที่สำคัญผมใช้ IPAD แล้วรู้สึกเมื่อยมือครับ เกร็งไปหมด กดแรงก็กลัว touch screen พัง

gmail.com block ip address

google block ip address
google block ip address

2 ก.ค.53 เรื่องเกิดจากเช้าวันนี้ หัวหน้าส่งเมลมาบอกว่าเพื่อนใน list จำนวน 2 คนใน gmail.com ไม่ได้รับอีเมล มี message ตอบกลับมาว่า gmail blocked ip address เป็นผลให้สมาชิกในองค์กร ส่งอีเมลไป gmail.com ไม่ได้ พบอาการวันอาทิตย์ และผมทดสอบวันจันทร์แล้วก็เป็นจริง
การดำเนินการมีดังนี้ 1) เข้าตาม link ที่ google.com แนะนำ แต่ไม่พบคำแนะนำที่นำไปสู่การแก้ปัญหาอย่างชัดเจน 2) เปลี่ยน ip เครื่องส่งเมลเป็นเครื่องที่สอง พบว่าส่งอีเมลถึง gmail.com ได้ แล้วผมก็รีบเปลี่ยนกลับ เพราะต้องตรวจให้พบก่อนว่าสาเหตุ และวิธีแก้ไขคืออะไรกันแน่ 3) สาเหตุน่าจะมาจากเครื่องบริการส่งอีเมลขยะจำนวนมาก ต้องหยุดการส่งก่อน 4) เข้าค้นในกระดานเสวนาของ gmail.com พบว่า ผู้ดูแลระบบหลายคนพบปัญหานี้ แต่กำลังหาทางแก้ปัญหากันอยู่ ซึ่งทางแก้ปัญหาเป็นไปได้หลายทาง 5) เข้าตรวจ maillog ของเครื่องบริการ พบว่ามีการใช้บริการจากภายนอก ส่งอีเมลแบบ bulk email ทำให้เครื่องทำงานตลอดเวลา หาวิธี config postfix แล้วก็ได้ผลไม่เป็นที่น่าพอใจ 6) กำหนด relay ไปที่ mail.cat.net.th ทำให้เครื่องบริการหยุดส่งอีเมลขยะ และรับอีเมลเข้าสู่ระบบได้ตามปกติ 7) แก้ไข squirrelmail ให้ส่งอีเมลจากเครื่องบริการตัวที่สอง ทำให้รับอีเมลจากสถาบันได้ตามปกติ .. สรุปคือ เครื่องบริการทำงานปกติแล้ว แต่ปัญหา config postfix ยังไม่ได้รับการแก้ไขซะทีเดียว เพราะมีหลายอย่างผูกกันอยู่ ต้องหาโอกาสเข้าไปคลายอีกครั้ง

การตรวจเครื่องบริการของเราผ่านเว็บไซต์ที่รับตรวจสอบ

29 ก.ค.53 เนื่องจาก host จำนวน 2 ตัว ไม่สามารถเข้าถึงจากภายนอกองค์กร จึงต้องมีการตรวจสอบแบบออนไลน์ หาสาเหตุว่าทำไมภายนอกไม่รู้จัก host เหมือนกับที่ภายในองค์กรรู้จัก ความเป็นไปได้คือ มีข้อกำหนดของเครื่องบริการที่บางข้อที่เป็นเหตุให้ไม่สามารถเข้าถึงจากภายนอกได้อย่างสมบูรณ์ จึงต้องใช้เครื่องมือจากหลายแหล่งช่วยตรวจ และแก้ไขไปตามอาการ

เครื่องมือตรวจบริการ website dns และ host แบบออนไลน์
1. speedtest.net ตรวจความเร็วในการเชื่อมต่ออินเทอร์เน็ต
2. ninjacloak.com บริการเข้าถึงเว็บไซต์ผ่าน proxy website
3. zend2.com บริการเข้าถึงเว็บไซต์ผ่าน proxy website
4. internet.nectec.or.th/netservices/ ตรวจการเปิด port
5. network-tools.com ตรวจผลของ nslookup และ blacklist
6. dnsstuff.com ตรวจ traceroute และตรวจการ block ping
7. my-addr.com ตรวจการเปิด port ของ host
8. robtex.com ตรวจวิเคราะห์ dns ตาม host
9. intodns.com ตรวจค่า config ของ dns