顯示具有 java 標籤的文章。 顯示所有文章
顯示具有 java 標籤的文章。 顯示所有文章

2015年2月13日 星期五

[Android] 倒數計時器

倒數計時可以分為兩種

1.可重複的

2.不可重複的

第一種當然就是使用Thread囉!

不斷用while()讓他重複

第二種比較簡單一點:

我們使用到CountDownTimer()這個類別

http://developer.android.com/reference/android/os/CountDownTimer.html

官網的解釋:

Public Methods


public final synchronized void cancel ()

Added in API level 1
Cancel the countdown.

public abstract void onFinish ()

Added in API level 1
Callback fired when the time is up.

public abstract void onTick (long millisUntilFinished)

Added in API level 1
Callback fired on regular interval.
Parameters
millisUntilFinishedThe amount of time until finished.

public final synchronized CountDownTimer start ()

Added in API level 1
Start the countdown.
除了start(),cancel以外

就是onFinish() ->倒數結束以後要幹嘛?

onTick()->每次減少固定單位時間時要做甚麼?

 new CountDownTimer(30000, 1000) {

     public void onTick(long millisUntilFinished) {
         mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
     }

     public void onFinish() {
         mTextField.setText("done!");
     }
  }.start();

官方網站也很貼心的提供程式碼

當然是要建立一個TextView 叫做mTextField (記得要findViewById)

然後他就會在上面顯示倒數多少秒這樣~

CounDownTimer(總共倒數多少秒 , 每次扣多少)

每1000為一秒, 所以30000 = 30 秒 , 1000 = 1秒

範例為倒數30秒,每次扣一秒.

十分容易吧! End



2014年10月17日 星期五

[Android] Sign & Unsign number (0~256) vs (-128~127)

*不一定是完全正確,可參考*

寫android寫到一個難題,解決了以後把他記下來,以免下次又忘記。

這個問題java也會遇到(其實android根本就是用java寫的....),所以java的也可以稍微參考一下

-----------------------------------------------------------------------------------------------------------------------

在android 裡面byte是沒辦法超過127的,所以如果我們要丟128以上的數字出去,就必須要作調整

不然即使強制轉換: (byte)129 這樣 ,仍然無法使用。java的世界裡面只有


0~127(正數)

---------------------------------

128~255(必須用負數表示)


在255的時候為 -1 因此.....128必須用-128表示(128-256 = -128)

也就是說 if( x > 127){
                      x = x-256;
                    }

這樣java才看得懂。

有看到網路上的人用&&FF ,不過那方法我也不太懂,所以就沒用了。

End.
               

2014年8月11日 星期一

[Android/Java] Thread(執行緒)的使用+UDP Send / Receive+Socket

在使用Thread的時候,必須要先知道執行緒(Thread)是甚麼?

否則只是看看範例,卻只得其一不得其二。

執行緒是一種可以在程式背景執行的一個Process(程序),同時可以有多個執行緒一起執行。

由於可以多線程,因此大大增加可用性。

Thread的結構大概就是

public class ChatServer extends Thread{

private DatagramSocket server = null;
private static final int PORT = 4000;
        //宣告變數

public ChatServer() throws IOException {
server = new DatagramSocket(PORT);
Log.d("User","new server socket");
}
        //建構子

public void run(){
byte[] byte100 = new byte[100];
DatagramPacket dPacket = new DatagramPacket(byte100, 100);
String txt;
try{
Log.d("User","runing run()");
while(true){
server.receive(dPacket);
Log.d("User","While 1");
while(true)
{
//印出來到螢幕上
Log.d("User","While 2");
if(true) break;
}
//CloseSocket(client);//關閉
}
}
catch(IOException e)
{}
}
        //主要在跑的地方(主程式)

在呼叫Thread的時候,以上面範例為例,我們呼叫時使用:  

       chatserver = new ChatServer();
       new這個class,他會跑進建構子裡面,但還不會進去run()函式
       chatserver.start();
       執行run()這個函式,由於run裡面有while()迴圈,所以會一直跑不停

       (在這兩行外面要夾try catch否則會有error)

-----------------------------------------------------------------------------------------------------------
上面解釋完Thread了,下面要講的是如何在Android上面使用執行緒的概念做UDP的發送與接收,

但這目前有個問題就是模擬器(emulator)與電腦的連線還沒有試做成功,在Emulator-Emulator是可

以成功傳送-接收的。

傳送部分:

目標:寫一個Thread,讓他不停傳送給指定IP+指定Port

內容:

public class ChatSender extends Thread{

public void run(){
DatagramSocket socket = null;
try
{
socket = new DatagramSocket();
InetAddress serverAddress = InetAddress.getByName("127.0.0.1");
Log.d("IP Address", serverAddress.toString());
String str = "Test Thread sender";
               //創建一個用於發送的DatagramPacket對象
               DatagramPacket packet=new DatagramPacket(str.getBytes(),str.length(),serverAddress,4000);
            //發送數據
            while(true)
            {
            socket.send(packet);
            Thread.sleep(1000);
            }
}
catch(SocketException e)
{
e.printStackTrace();
String error = e.toString();
Log.e("Error by Sender", error);
}
catch(UnknownHostException e)
{
e.printStackTrace();
String error = e.toString();
Log.e("Error by Sender", error);
}
catch(IOException e)
{
e.printStackTrace();
String error = e.toString();
Log.e("Error by Sender", error);
}
catch(Exception e)
{
e.printStackTrace();
String error = e.toString();
Log.e("Error by Sender", error);
}
finally{
if(socket != null){
socket.close();
}

}
}
}

大概可以看到DatagramSocket+DatagramPacket這兩個API,

DatagramSocket我的理解是用於Socket連線,而DatagramPacket則是負責傳送的封包內容。

*DatagramPacket(封包的byte[]陣列,封包的長度,IP位址,Port); 

至於InetAddress的部分是為了要確定本機IP是多少。


接收部分:

目標:寫一個Thread,讓他不停到指定的Port接收封包,直到有接收到才印出來,之後繼續hold住等待封包傳送過來。

內容:

public class ChatServer extends Thread{

private DatagramSocket server = null;
private static final int PORT = 4000;

public ChatServer() throws IOException {
server = new DatagramSocket(PORT);
Log.d("User","new server socket");
}
public void run(){
byte[] byte100 = new byte[100];
DatagramPacket dPacket = new DatagramPacket(byte100, 100);
String txt;
try{
Log.d("User","runing run()");
while(true){
server.receive(dPacket);
Log.d("User","While 1");
while(true)
{
//印出來到螢幕上
Log.d("User","While 2");
if(true) break;
}
//CloseSocket(client);//關閉
}
}
catch(IOException e)
{}
}

private void CloseSocket(DatagramSocket socket) throws IOException{
socket.close();
}
}

UDP接收的部分同樣也需要DatagramSocket/DatagramPacket,不過剛剛是Send 現在則是receive

為了存放接收的資料,前面會先new一個byte[]陣列用以存放資料。

在server.receive(dPacket);這邊如果沒有資料進來的話,他不會往下跑,會一直等待在這邊,直到接

收到資料才會執行下一行。這是必須特別注意的!


MainActivity的部分:

public class MainActivity extends ActionBarActivity {

private Handler exHandler;
private TextView txv;
private ChatServer chatserver;
private ChatSender chatsender;
public static InetAddress IP;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txv = (TextView) findViewById(R.id.textView);
try{
//IP = InetAddress.getLocalHost();
chatserver = new ChatServer();
chatserver.start();
chatsender = new ChatSender();
chatsender.start();
Log.d("User","Thread start...");
}catch(Exception e)
{
String str = e.toString();
Log.e("Error by User", str);
}
}
protected void onPause(){
super.onPause();
if(chatserver != null)
{
if(!chatserver.isInterrupted())
{
chatserver.interrupt();
}
}
}

然後要記得AndroidManifest.xml這邊要增加INTERNET的Uses-Permission

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.thread_example"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="19" />
    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.thread_example.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>


結論: UDP 傳送及接收其實不容易,看似簡單但很多細節如果沒有注意到就會失敗!



2014年5月14日 星期三

[Android APP] 初探Android APP開發

首先,

前面文章有寫過如何安裝 在這篇, 在經過幾次範例練習後大概有一些心得。

先寫起來以免忘記,當然都是一些基本觀念(新手容易犯的錯誤)

1.專案開起來後設計圖形介面錯誤

正確路徑檔案是在: res資料夾->layout->activity_main.xml 而不是 Fragment_main.xml

(如果寫在Fragment_main.xml會造成java.lang.null point exception 因為它找不到)

2.變數宣告位置錯誤

新手往往會有一個錯誤就是宣告變數再protected void onCreate()的裡面,

但是當這App還沒有被創建時候,是沒有這變數,因此也會造成錯誤,切記切記。

3. 遇到 " error: No resource identifier found for attribute "類似這樣的問題,有可能是更改最底層的Layout

造成的問題(id為container的layout),可以嘗試按右鍵選擇Change Layout,有機會可以去除掉錯誤。

4.在implement監聽物件的時候,MainActivity會需要 -> add unimplement method (程式碼旁邊會有一

個小燈泡,按下去會有這選項)他會幫你新增onXXXChange()這個函式(如果要自己輸入,記得上方

要加入@override,不然還是會有錯)



(未完待續.....)

2014年3月7日 星期五

[Android] Google Android APP 開發環境安裝

1.需要Java JDK

http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html

選擇符合自己作業系統的版本

2.下載

http://developer.android.com/sdk/index.html

installer_r20.0.1-windows.exe  + ADT bundle for windows

3.安裝installer_r20.0.1 (要調整為install for anyone using this computer ,預設為just for me)

下一步下一步......完成

4.打開Android SDK Manager 選 Android其中一個版本 然後按下install X(看有多少個) Packages...

會開始更新,很久,可以休息一下喝杯水再過來

5.改JAVA環境變數(跟linux根本一樣)

到[系統及安全性]->[系統]->[進階系統設定](在左側) 進入以後 選 [進階]->下面有{環境變數} 按鈕,進入以後


(如文字描述)

將你安裝的JDK的bin資料夾路徑ex: C:\Program Files\Java\jdk1.7.0_51\bin 加入 "系統變數"的Path值中,如果前面有東西,或後面還要加東西請用分號區隔。

然後再加入Android SDK tools & Platform-tools兩個資料夾(也在program files\android....可以找到)

所以總共是:

加入;C:\Program Files\Android\android-sdk\tools;C:\Program Files\Android\android-sdk\platform-tools

;是為了區隔前後,不是打錯(以上三個都要(編輯)加入在Path中)

選取 "系統變數"的CLASSPATH(如果沒有就新增) 按 編輯 加入  C:\Program Files\Java\jdk1.7.0_51\lib (是lib資料夾,不是bin)

6.開始->程式->Android SDK tools ->AVD Manager

按New即可新增一個模擬器,設定可以自己調。(要調整SD卡的話一定要給sdcard空間,不然權限會不足)->按下Start就會開始emulate(模擬),超級超級超級久.....然後就可以測試囉!

7.cmd 命令提式字元 先進到platform-tools目錄

adb.exe shell( root權限 Linux指令)

adb.exe push 檔案 手機內的路徑(pull為下載,push為上傳)

可以在Android SDK 下的tools 找到ddms.bat 打開可以看file explore 或是模擬傳簡訊。

End