การเปิด Navigator ด้วย Intent

nav

การเปิด Google Navigator

//String destination = "16.5643123,100.986754"; // กำหนดปลายทางแบบพิกัด Lat ,Lng
String destination = "อ.เมือง จ.พิษณุโลก"; // กำหนดปลายทางแบบชื่อสถานที่
Intent intent = new Intent(android.content.Intent.ACTION_VIEW,Uri.parse("google.navigation:q="+destination));
startActivity(intent);

การเปิด Sygic Navigator

String str = "com.sygic.aura://coordinate|15.996591|100.3413341|drive"; 
startActivity( new Intent(Intent.ACTION_VIEW, Uri.parse(str)) );

รายละเอียดเพิ่มเติมของ Sygic

ควบคุมระดับเสียงด้วย SeekBar และ ปุ่ม เพิ่ม-ลด เสียง

device-2557-01-24-214544

ตัวอย่างนี้จะเป็นการสร้างแอพเพื่อควบคุมระดับเสียงด้วย SeekBar และ ปุ่ม เพิ่ม-ลด เสียง (ปุ่มด้านข้างของเครื่อง) โดยเมื่อผู้ใช้ทำการเลื่อน seekbar ระดับเสียงจะเพิ่มลดไปตามค่าของการเลื่อน และเมื่อกดปุ่ม เพิ่ม-ลด เสียง ด้านข้าง ก็จะทำให้ seekbar เลื่อนตามอีกด้วย

โปรเจคนี้ก็ไม่มีอะไรยากครับ ก็ให้ผู้อ่านสร้าง Android Project ขึ้นมา

Project Name: VolumeSeekBar
Min SDK : 10

แก้ไขไฟล์ activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/LinearLayout2"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center|top"
    android:orientation="vertical"
    android:padding="15dp"
    tools:context=".MainActivity" >
    <TextView
        android:id="@+id/textView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="volume with seekbar" />
    <SeekBar
        android:id="@+id/seekBar1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/tvValue"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="0" />
</LinearLayout>

จากนั้นแก้ไขไฟล์ MainActivity.java

package utehn.dev.volumeseekbar;
import android.app.Activity;
import android.content.Context;
import android.media.AudioManager;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.view.KeyEvent;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;

public class MainActivity extends Activity {

	SeekBar volumeSeekbar;
	TextView tvValue;
	AudioManager audioManager = null;
	Ringtone ring;

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

		Uri ringtone = RingtoneManager
				.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
		ring = RingtoneManager.getRingtone(getApplicationContext(), ringtone);
		ring.play(); //เล่น ringtone เมื่อเริ่มแอพ

		volumeSeekbar = (SeekBar) findViewById(R.id.seekBar1);
		tvValue = (TextView) findViewById(R.id.tvValue);

		audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);

		volumeSeekbar.setMax(audioManager
				.getStreamMaxVolume(AudioManager.STREAM_RING));
		volumeSeekbar.setProgress(audioManager
				.getStreamVolume(AudioManager.STREAM_RING));

		int initvalue = volumeSeekbar.getProgress();
		tvValue.setText(String.valueOf(initvalue));

		volumeSeekbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
			@Override
			public void onStopTrackingTouch(SeekBar arg0) {
			}

			@Override
			public void onStartTrackingTouch(SeekBar arg0) {
			}

			@Override  // เหตุการณ์เมื่อเลื่อน seekbar
			public void onProgressChanged(SeekBar arg0, int progress,
					boolean arg2) {
				audioManager.setStreamVolume(AudioManager.STREAM_RING,
						progress, 0);
				tvValue.setText(String.valueOf(progress));
			}
		});

	}

	public void onDestroy() {
		ring.stop();
		super.onDestroy();

	}

	@Override // เหตุการณ์เมื่อกดปุ่ม เพิ่ม-ลด ด้านข้าง
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
			int val = volumeSeekbar.getProgress();
			volumeSeekbar.setProgress(val + 1);
			return true;
		} else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
			int val = volumeSeekbar.getProgress();
			volumeSeekbar.setProgress(val - 1);
			return true;
		}
		return super.onKeyDown(keyCode, event);
	}

}

การติดตั้ง Mobile Emulater (Ripple Emulator)ให้กับ Google Chrome

Image 1

Ripple Emulator เป็น extension ของ google chrome เอาไว้สำหรับดูเวบไซต์ในมุมมองของ Mobile Device ครับ
เหมาะสำหรับ web programmer ที่พัฒนา responsive web , jquery mobile

การติดตั้งก็ไม่ได้มีความยุ่งยากอะไร

ก่อนอื่นให้เข้าไปที่ webstore ของ chrome ตามลิงค์ด้านล่าง

https://chrome.google.com/webstore/detail/ripple-emulator-beta/geelfhphabnejjhdalkjhgipohgpdnoc

คลิกตรงปุ่ม ฟรี ตามลูกศรชี้ จากนั้นคลิก add รอ chrome ติดตั้ง ripple สักครู่
Image 6

เมื่อติดตั้ง ripple เสร็จแล้วให้ลองคลิกขวาบนพื้นที่แสดงผลของ chrome
จะเห็นว่ามีเมนู emulator ปรากฏขึ้นมา ลองคลิก enable ดูครับ
Image 4

Image 8
ก็จะมีเมนูตั้งค่า emulator ปรากฏขึ้นมา ลองตั้งค่าตามใจชอบครับ

Image 9

ทำ EditText ให้มีขอบโค้งมน

device-2556-09-20-092449

ให้สร้างไฟล์ res/drawable/edittext_rounded_corners.xml ขึ้นมา แล้วใส่ code ตามด้านล่าง

<?xml version="1.0" encoding="utf-8"?>
<!-- res/drawable/edittext_rounded_corners.xml -->

<selector xmlns:android="http://schemas.android.com/apk/res/android">

<item android:state_pressed="true" android:state_focused="true">
    <shape>
        <solid android:color="#FF8000"/>
        <stroke
            android:width="2.3dp"
            android:color="#FF8000" />
         <corners
            android:radius="15dp" />
    </shape>
</item>

<item android:state_pressed="true" android:state_focused="false">
    <shape>
        <solid android:color="#FF8000"/>
        <stroke
            android:width="2.3dp"
            android:color="#FF8000" />      
        <corners
            android:radius="15dp" />       
    </shape>
</item>

<item android:state_pressed="false" android:state_focused="true">
    <shape>
        <solid android:color="#FFFFFF"/>
        <stroke
            android:width="2.3dp"
            android:color="#FF8000" />  
        <corners
            android:radius="15dp" />                          
    </shape>
</item>

<item android:state_pressed="false" android:state_focused="false">
    <shape>
        <gradient 
            android:startColor="#F2F2F2"
            android:centerColor="#FFFFFF"
            android:endColor="#FFFFFF"
            android:angle="270"
        />
        <stroke
            android:width="0.7dp"                
            android:color="#BDBDBD" /> 
        <corners
            android:radius="15dp" />            
    </shape>
</item>

<item android:state_enabled="true">
    <shape>
        <padding 
                android:left="4dp"
                android:top="4dp"
                android:right="4dp"
                android:bottom="4dp"
            />
    </shape>
</item>

</selector>

ส่วนในไฟล์ layout ก็ใส่ background ให้กับ edittext ตัวที่เราต้องการให้มีขอบโค้งมน

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

    <EditText
        android:id="@+id/etTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/edittext_rounded_corners"
        android:ems="10"
        android:hint="Title" >
    </EditText>

    <EditText
        android:id="@+id/etMsg"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:ems="10"
        android:hint="Message" />    
</LinearLayout>

การพัฒนา Google Map Andriod API V2 ให้รองรับ Android ที่มี Sdk Version ต่ำกว่า 11

Image 11
รายละเอียดตามเอกสารแนบ
https://docs.google.com/file/d/0B1T2d66GNAR-azNfTFk5LXhvZ1U/edit?usp=sharing

jQueryMobile ทำ left slide panel แบบ facebook app

Image 1

Image 2

ไฟล์ index.html

<!doctype html>
<html>

    <head>

        <meta charset="utf-8">       
        <meta name="viewport" content="width=device-width, minimum-scale=1, maximum-scale=1">
        <title>Mobile</title>
        <link rel="stylesheet" href="http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.css" />
        <link rel="stylesheet" href="left-panel.css" />
        <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
        <script src="http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.js"></script>

    </head>

    <body>

        <div data-role="page" id="demo-page" data-theme="d" data-url="demo-page">

            <div data-role="header" data-theme="c">
                <h1>Header</h1>
                <a href="#left-panel" data-icon="bars" data-iconpos="notext" data-shadow="false" data-iconshadow="false">Menu</a>
            </div><!-- /header -->

            <div data-role="content">
                <p>content content content content content content content content</p>
            </div><!--/content-->

            <div data-role="footer" data-theme="c">
                <h4>footer</h4>
            </div><!-- /footer-->

            <div data-role="panel" id="left-panel" data-theme="c">
                <ul data-role="listview" data-theme="d">
                    <li  data-icon="arrow-l"><a href="#" data-rel="close"></a></li>
                    <li data-role="list-divider">Menu</li>
                    <li data-icon="gear"><a href="#">ตั้งค่า</a></li>                    
                    <li data-icon="delete"><a href="#">ออก</a></li>
                </ul>
            </div><!-- /panel -->

        </div>><!-- /page -->


    </body>

</html>

ไฟล์ left-panel.css

/* Adjust the width of the left reveal menu.
Copy all CSS from jquery.mobile.panel.css and delete the properties other than width, left, right and transform.
Then delete the selectors/rules for display modes (reveal/push/overlay) and the position (left/right) that you don't use.
If you don't use fixed toolbars on your page you can delete those selectors as well.
Narrow the scope of the selectors to prevent other panels being affected by the overrides. */
#demo-page #left-panel.ui-panel {
    width: 15em;
}
#demo-page #left-panel.ui-panel-closed {
    width: 0;
}
#demo-page .ui-panel-position-left.ui-panel-display-reveal {
    left: 0;
}
#demo-page .ui-panel-content-wrap-position-left.ui-panel-content-wrap-open,
.ui-panel-dismiss-position-left.ui-panel-dismiss-open {
    left: 15em;
    right: -15em;
}
#demo-page .ui-panel-animate.ui-panel-content-wrap-position-left.ui-panel-content-wrap-open.ui-panel-content-wrap-display-reveal {
    left: 0;
    right: 0;
    -webkit-transform: translate3d(15em,0,0);
    -moz-transform: translate3d(15em,0,0);
    transform: translate3d(15em,0,0);
}
/* Combined listview collapsible menu. */
/* Unset negative margin bottom on the listviews. */
#left-panel .ui-panel-inner > .ui-listview { margin-bottom: 0; }
/* Unset top and bottom margin on collapsible set. */
#left-panel .ui-collapsible-set { margin: 0; }
/* The first collapsible contains the collapsible set. Make it fit exactly in the collapsible content. */
#left-panel .ui-panel-inner > .ui-collapsible > .ui-collapsible-content { padding-top: 0; padding-bottom: 0;  border-bottom: none; }
/* Remove border top if a collapsible comes after a listview. */
#left-panel .ui-panel-inner  > .ui-collapsible > .ui-collapsible-heading .ui-btn,
#left-panel .ui-collapsible.ui-first-child .ui-collapsible-heading .ui-btn { border-top: none; }
/* Give the first collapsible heading the same padding, i.e. same height, as the list items. */
#left-panel .ui-collapsible-heading .ui-btn-inner { padding: .7em 40px .7em 15px; }
/* Give the other collapsible headings the same padding and font-size as the list divider. */
#left-panel .ui-collapsible-set .ui-collapsible-heading .ui-btn-inner { padding: .5em 40px .5em 15px; font-size: 14px; }
/* Styling of the close button in both panels. */
#demo-page .ui-panel-inner > .ui-listview .ui-first-child {
    background: #eee;
}
/* Reveal menu shadow on top of the list items */
#demo-page .ui-panel-display-reveal {
    -webkit-box-shadow: none;
    -moz-box-shadow: none;
    box-shadow: none;
}
#demo-page .ui-panel-content-wrap-position-left {
    -webkit-box-shadow: -5px 0px 5px rgba(0,0,0,.15);
    -moz-box-shadow: -5px 0px 5px rgba(0,0,0,.15);
    box-shadow: -5px 0px 5px rgba(0,0,0,.15);
}
/* Use the ui-body class of your page theme to set a background image.
The page theme will be set for the content wrapper,
while the page get the panel them before opening the panel. */
#demo-page .ui-body-d {
    background-image: url(../../_assets/img/bg-pattern.png);
    background-repeat: repeat-x;
    background-position: left bottom;
}
/* Styling of the page contents */
.article p {
    margin: 0 0 1em;
    line-height: 1.5;
}
.article p img {
    max-width: 100%;
}
.article p:first-child {
    text-align: center;
}
.article small {
    display: block;
    font-size: 75%;
    color: #c0c0c0;
}
.article p:last-child {
    text-align: right;
}
.article a.ui-btn {
    margin-right: 2em;
    -webkit-border-radius: .4em;
    border-radius: .4em;
}
@media all and (min-width:769px) {
    .article {
        max-width: 994px;
        margin: 0 auto;
        padding-top: 4em;
        -webkit-column-count: 2;
        -moz-column-count: 2;
        column-count: 2;
        -webkit-column-gap: 2em;
        -moz-column-gap: 2em;
        column-gap: 2em;
    }
    /* Fix for issue with buttons and form elements
    if CSS columns are used on a page with a panel. */
    .article a.ui-btn {
        -webkit-transform: translate3d(0,0,0);
    }
}

ทำ App สองภาษา ง่ายๆ ด้วย Android Studio

Image 4

ตัวอย่างนี้แนะนำวิธีการทำ App 2 ภาษา (อังกฤษ-ไทย)
ซึ่งภาษาจะเปลี่ยนไปตามการตั้งค่าบนตัวเครื่องของเราครับ

step0 : เปิดไฟล์ layout ขึ้นมา ในตัวอย่างเปิด res/layout/activity_main.xml และเลือกให้อยู่ในโหมด design
Image 5

step1: คลิกที่ ปุ่ม Add Translation แล้วเลือก Thai (th) ดังรูป
Image 1

step2: ในช่อง Thai (Th) กรอก ข้อความที่เป็นภาษาไทย ดังรูป เสร็จแล้วกด OK
Image 2

step3: โปรแกรม Android Studio จะสร้างไฟล์ res/values-th/strings.xml ให้อัตโนมัติ ดังรูป
Image 3

step4: คลิกที่ปุ่มรูปธงชาติไทย จะเห็นว่า Layout ในส่วนที่เรากำหนดค่าภาษาไทยให้ จะเปลี่ยนเป็นภาษาไทย
Image 4

ส่วนใน Eclipse ก็สามารถทำได้โดยสร้าง ไฟล์ res/values-th/strings.xml ขึ้นมาเองได้เหมือนกันครับ

การติดตั้ง Android บน VirtualBox ไว้ใช้ดีบัก App

Image 28

ปัญหาอย่างนึงของการใช้ Emulator ในการ debug คือ emulator ทำงานได้ช้าเอามากๆ อีกอย่างบางทีหากเราเขียน app ที่เรียกใช้ Libray Google play service เจ้า Emulator ก็ไม่รองรับอีก(แต่ Google ได้แจ้งว่า Emulator ที่มี API V 17 รองรับแล้ว) ทางแก้ปัญหาก็คือ debug บนเครื่องจริง??
แต่ถ้าไม่มีเครื่องจริงก็ใช้วิธีลง Android บน VirtualBox ได้อีกทางครับ

ผมได้ทำสไลด์ขั้นตอนการลง Android บน Virtual Box ไว้ให้ผู้ที่สนใจ ตามลิงค์ด้านล่างนี้ครับ

ไฟล์ PDF : http://www.4shared.com/office/Yqc-AoHU/AndroidOnVM.html
ไฟล์ PowerPoint : http://www.4shared.com/file/nRd-RoXY/AndroidOnVM.html

เครดิต : http://www.genymotion.com/

Jquery Moblie ดึงพิกัด GPS

gps

ไฟล์ gps.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name=viewport content="user-scalable=no,width=device-width" />
        <link rel="stylesheet" href="http://code.jquery.com/mobile/1.3.1/jquery.mobile-1.3.1.min.css" />
        <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
        <script src="http://code.jquery.com/mobile/1.3.1/jquery.mobile-1.3.1.min.js"></script>
    </head>
    <body>
        <div data-role=page id=home>
            <div data-role=header data-theme="b"><h1>พิกัด GPS</h1></div>

            <div data-role=content>
                <span> สถานะ : </span> <span id=state></span> <br />
                <span> เวลา : </span> <span id=time></span> <br />
                <span> Latitude : </span> <span id=lat></span> <br />
                <span> Longitude : </span> <span id=lng></span> <br />
            </div>
            <div align="center">
                <input data-theme="c" type="button" name="btn_start" value="Start" id="btn_start" data-inline="true" data-icon="check">
                <input data-theme="e" type="button" name="btn_stop" value="Stop" id="btn_stop" data-inline="true" data-icon="delete">
            </div>
            <div align="center">
                <div id="out_put" style="width:99%; height:300px; overflow:scroll; border:1px solid #000;"></div>
            </div>
            <br>
             <div data-role=footer data-theme="b" data-position="fixed"><h4>By Android4Health</h4></div>
        </div>
    </body>
</html>

<script>
    (function($) {
        var runGPS = 0;
        $('#btn_start').click(function() {
            $("#state").text('Running');
            runGPS = 1;
        });
        $('#btn_stop').click(function() {
            $("#state").text('Paused');
            runGPS = 0;
        });
        var timer = setInterval(function() {
            if (runGPS == 1) {
                navigator.geolocation.getCurrentPosition(function(pos)                {
                    date = new Date();
                    $("#time").text(date);
                    var lat = pos.coords.latitude;
                    var lng = pos.coords.longitude;
                    $("#lat").text(lat);
                    $("#lng").text(lng);
                    var t = date + " lat:" + lat + "lng:" + lng + "<br>";
                    $("#out_put").append(t);
                });
            }
        }, 1000);
    })(jQuery);
</script>

การแสดงเวลาแบบมีตัวเลขวินาทีวิ่งอยู่ตลอดเวลา

device-2556-06-07-095526

ตัวอย่างนี้เป็นการประยุกใช้ background thread สั่ง update UI Thread ในการแสดงเวลาแบบมีตัวเลขวินาทีวิ่งอยู่ตลอดเวลา …ครับ

- ไฟล์ MainActivity.java

package utehn.dev.clockdroid;
//import bla bla
public class MainActivity extends Activity {

    private TextView tv_time;

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

        tv_time =(TextView)findViewById(R.id.tv_time);

        Runnable mRunnableThread = new TimeRunner();
        Thread mThread= new Thread(mRunnableThread);
        mThread.start();
    }//end onCreate

    class TimeRunner implements Runnable{
        @Override
        public void run() {
            while(!Thread.currentThread().isInterrupted()){
                try {

                    runOnUiThread(new Runnable() {
                        public void run() {
                            try{
                                tv_time.setText(java.text.DateFormat.getDateTimeInstance().format(Calendar.getInstance().getTime()));
                            }catch (Exception e) {}
                        }
                    });

                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }catch(Exception e){
                }
            }
        }
    }// end Runnable Class
    
}

-ไฟล์ activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"   
    tools:context=".MainActivity">

    <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"          
            android:text="Large Text"
            android:id="@+id/tv_time"    
           />

</RelativeLayout>
ติดตาม

Get every new post delivered to your Inbox.