分類
Android Uncategorized

Android Worker Thread Advanced

上篇 Android Looper + Handler + Message + MessageQueue(Worker Thread)介紹 Worker Thread (Android訊息傳送機制)
本篇會持續示範訊息傳送機制的其他進階用法,

1.傳送訊息夾帶參數

這是基本建立訊息並使用Handler傳送訊息的用法

    private void sendMessageToWorkerHandler()
    {
        Handler handler = mCustomizeWorkerThread.getHandler();
        if (handler != null) {
            Message message = handler.obtainMessage(2);
            handler.sendMessage(message);
        }
    }

傳送訊息可以夾帶參數,讓Handler在處理訊息(handleMessage方法)時,可根據參數作更多處理 e.g.,
夾帶簡單整數型態arg1和arg2

    private void sendMessageWithArgsToWorkerHandler()
    {
        Handler handler = mCustomizeWorkerThread.getHandler();
        if (handler != null) {
            Message message = Message.obtain();
            message.what = 3;
            message.arg1 = 10;
            message.arg2 = 100;
            handler.sendMessage(message);
        }
    }

另外還可以夾帶自定義類別的物件,以下為自定義類別,為了簡單示範,只持有一個String和一個Int類別成員

package com.foxx.threads;
public class CustomizeMessageObject
{
    private String mName = "";
    private int mType;
    public CustomizeMessageObject(String name, int type){
        mName = name;
        mType = type;
    }
    public String getName()
    {
        return mName;
    }
    public void setName(String name)
    {
        mName = name;
    }
    public int getType()
    {
        return mType;
    }
    public void setType(int type)
    {
        mType = type;
    }
}

夾帶自定義物件的方式

    private void sendMessageWithObjectToWorkerHandler()
    {
        Handler handler = mCustomizeWorkerThread.getHandler();
        if (handler != null) {
            Message message = Message.obtain();
            message.what = 4;
            message.obj = new CustomizeMessageObject("Foxx", 123);
            handler.sendMessage(message);
        }
    }

修改在Activity發送訊息的部份,點擊按鈕會依序發送3個訊息

    @Override
    public void onClick(View view)
    {
        int uiId = view.getId();
        switch (uiId) {
            case R.id.startThread:
                sendMessageToWorkerHandler();
                sendMessageWithArgsToWorkerHandler();
                sendMessageWithObjectToWorkerHandler();
                break;
        }
    }

修改CustomizeWorkerHandler處理訊息的部份,針對message.what的數值作判斷

    public void handleMessage(Message message)
    {
        switch (message.what) {
            case 2:
                String result = HttpPageData.getPageData("https://www.google.com.tw/");
                setResultToMainActivity(result);
                break;
            case 3:
                Log.d(TAG, "message.arg1:" + message.arg1);
                Log.d(TAG, "message.arg2:" + message.arg2);
                break;
            case 4:
                CustomizeMessageObject messageObject = (CustomizeMessageObject) message.obj;
                Log.d(TAG, "MessageObject.name:" + messageObject.getName());
                Log.d(TAG, "MessageObject.type:" + messageObject.getType());
                break;
        }
    }

以下是Logcat的輸出

06-12 11:34:01.463: D/WorkerHandler(16289): message.arg1:10
06-12 11:34:01.463: D/WorkerHandler(16289): message.arg2:100
06-12 11:34:01.463: D/WorkerHandler(16289): MessageObject.name:Foxx
06-12 11:34:01.463: D/WorkerHandler(16289): MessageObject.type:123

 

2.提醒使用者訊息處理

假設處理訊息時並沒有提醒使用者,會讓使用者誤判點擊按鍵卻沒有反應造成使用者多次點擊,為了避免這種情況,最好在送出訊息時出現提示。
提示可由Dialog或是ProgressDialog組成。
首先在MainActivity加入並建立提示元件,提供外部存取的方法

public class MainActivity extends ActionBarActivity implements OnClickListener
{
    ...
    private AlertDialog mProcessingMessageDialog;
    private void initUIComponents()
    {
        initProcessingMessageDialog();
        ...
    }
    private void initProcessingMessageDialog()
    {
        mProcessingMessageDialog = new AlertDialog.Builder(this).create();
        mProcessingMessageDialog.setTitle("Processing...");
        mProcessingMessageDialog.setCanceledOnTouchOutside(false);
    }
    public AlertDialog getProcessingMessageDialog(){
        return mProcessingMessageDialog;
    }

接著在CustomizeWorkerHandler加入操作和呼叫點
第5行當該Handler收到從Looper傳送過來的訊息,立即顯示ProcessingMessageDialog
第21行當該Handler處理完Message,關閉ProcessingMessageDialog

class CustomizeWorkerHandler extends Handler
{
    public void handleMessage(Message message)
    {
        showProcessingDialog();
        switch (message.what) {
            case 2:
                String result = HttpPageData.getPageData("https://www.google.com.tw/");
                setResultToMainActivity(result);
                break;
            case 3:
                Log.d(TAG, "message.arg1:" + message.arg1);
                Log.d(TAG, "message.arg2:" + message.arg2);
                break;
            case 4:
                CustomizeMessageObject messageObject = (CustomizeMessageObject) message.obj;
                Log.d(TAG, "MessageObject.name:" + messageObject.getName());
                Log.d(TAG, "MessageObject.type:" + messageObject.getType());
                break;
        }
        closeProcessingDialog();
    }
    private void showProcessingDialog()
    {
        mMainActivity.runOnUiThread(new Runnable() {
            @Override
            public void run()
            {
                mMainActivity.getProcessingMessageDialog().show();
            }
        });
    }
    private void closeProcessingDialog()
    {
        mMainActivity.runOnUiThread(new Runnable() {
            @Override
            public void run()
            {
                mMainActivity.getProcessingMessageDialog().dismiss();
            }
        });
    }
}

 

3.雙重Handler溝通

CustomizeWorkerHandler 的 showProcessingDialog 和 closeProcessingDialog方法其實是為了調用UI Thread的UI元件。
如果把處理UI Thread的內容集中寫在CustomizeWorkerHandler,會調用多次的 mMainActivity.runOnUiThread方法,
導致CustomizeWorkerHandler類別的冗長,其實可以在UI Thread中建立另一個UI Handler,當CustomizeWorkerHandler有結果產生時
藉由UI Handler發送訊息到UI Thread,訊息包含處理完的結果,把結果的處理轉回到 UI Thread中。
先新增UIHandler類別並建立實體,提供存取方法,把結果的處理放在handleMessage方法中,順便修正Magic Number

public class MainActivity extends ActionBarActivity implements OnClickListener
{
    ...
    public static final int GET_PAGE_DATA = 0;
    public static final int SEND_MESSAGE_ARGS = 1;
    public static final int SEND_MESSAGE_OBJECT = 2;
    private UIHandler mHandler;
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        ...
        initUIHandler();
        ...
    }
    private void initUIHandler()
    {
        mHandler = new UIHandler();
    }
    public UIHandler getHandler()
    {
        return mHandler;
    }
    class UIHandler extends Handler
    {
        @Override
        public void handleMessage(Message msg)
        {
            switch (msg.what) {
                case GET_PAGE_DATA:
                    String result = (String) msg.obj;
                    mResultTextView.setText(result);
                    break;
                case SEND_MESSAGE_ARGS:
                    mResultTextView.setText(""+msg.arg1+msg.arg2);
                    break;
                case SEND_MESSAGE_OBJECT:
                    CustomizeMessageObject messageObject = (CustomizeMessageObject) msg.obj;
                    mResultTextView.setText(""+messageObject.getName()+messageObject.getType());
                    break;
            }
            mProcessingMessageDialog.dismiss();
        }
    }

修改CustomizeWorkerHandler在handlMessage方法取得UI Handler,並使用UI Handler發送包含結果的訊息,

class CustomizeWorkerHandler extends Handler
{
    ...
    @Override
    public void handleMessage(Message message)
    {
        Message messageToUIHandler = mMainActivity.getHandler().obtainMessage(message.what);
        switch (message.what) {
            case MainActivity.GET_PAGE_DATA:
                messageToUIHandler.obj = HttpPageData.getPageData("https://www.google.com.tw/");
                break;
            case MainActivity.SEND_MESSAGE_ARGS:
                messageToUIHandler.arg1 = message.arg1;
                messageToUIHandler.arg2 = message.arg2;
                break;
            case MainActivity.SEND_MESSAGE_OBJECT:
                CustomizeMessageObject messageObject = (CustomizeMessageObject) message.obj;
                messageToUIHandler.obj = messageObject;
                break;
        }
        mMainActivity.getHandler().sendMessage(messageToUIHandler);
    }
}

如此就能在UI Thread中處理結果。
 

分類
Android Uncategorized

Android Looper + Handler + Message + MessageQueue

本篇紀錄如何在Android中使用 Handler + Looper + Message + Queue。
為了讓App保持快速的回應性(避免產生ANR),長期任務不可執行在 UI thread上,這些長期任務包括,網路存取,讀寫檔案,資料庫存取,圖形處理等等。
在Android中使用Thread和在一般的Java中使用方式相當類似,但有一些同步化問題必須去解決,如 Race Condition, Blocking等等
為了方便解決這些問題,Android定義訊息傳送機制來確保訊息傳送的正確性以及安全性,Android訊息傳送機制包含4個角色,各為Looper,Handler,Message,MessageQueue。
 
Message :
訊息,由一組描述和一些資料物件所組成,可藉由Handler傳送到MessageQueue中,並由Looper取出再回傳給同一個Handler,當需要傳遞參數時,可夾帶在Message中。
建立Message的方式盡量使用Message.obtain(), 或是Handler.obtainMessage(),因為訊息會被放到緩衝池以重複使用。
 
MessageQueue :
訊息佇列,透過Looper建立,內容則是訊息組成,結構為無限制的連結串列,一個Looper只能有一個MessageQueue,
訊息會藉由Handler插入,並由Looper取出傳送到相對應的Handler。
 
Looper :
管理MessageQueue,會將存放於MessageQueue中的訊息依序送出到Handler上,讓Handler作進一步的處理,
Handler必須和Looper連結,否則無法傳送或接收訊息,而Thread也必須和Looper連結,才能讓MessageQueue和Thread相關連。
簡單的說Looper是Thread和MessageQueue的協調者。一個Thread只能有一個Looper。
 
Handler :
訊息處理者,在Android訊息傳送機制中,Handler是最常使用的類別,Handler可建立訊息,插入訊息到訊息佇列中,處理訊息。
一個Looper可以有多個Handler,Looper會自動將Message傳送給對應的Handler。
 
藉由以下的範例來說明彼此之間的互動,範例會盡量少用匿名內部類別來實作,而是把各個元件拆開為單一類別,比較容易了解
範例只有一個button和一個textview組成,當點擊button時,會去擷取 https://www.google.com.tw/ 的網頁資料
並顯示到textview上。
 
首先是 MainActivity,因為網路存取是長期任務,且android在Honeycomb SDK新增了NetworkOnMainThreadException,
若在Main thread(UI thread)進行網路操作,會丟出Exception。所以把網路操作放到CustomizeWorkerThread中執行,
第18行建立 mCustomizeWorkerThread 物件
第38行建立CustomizeWorkerThread物件並連結到參考,傳入this是為了把取得的網頁資料設定回MainActivity的textview
第39行呼叫start()方法以啟動mCustomizeWorkerThread的run方法。
第48行當按鈕按下時,呼叫sendMessageToWorkerHandler方法,該方法會建立message插入到MessageQueue
第55行取得mCustomizeWorkerThread的Handler,
第56行建立Message物件,其中數字2為Message的what欄位數值,當Handler處理Message時可以依此數值判斷行為。
第57行利用Handler將Message物件插入到MessageQueue中
第69行當activity結束時也告知Looper停止處理訊息

package com.foxx.threads;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends ActionBarActivity implements OnClickListener
{
    private static final String TAG = "MainActivity";
    private Button mStartThreadButton;
    private TextView mResultTextView;
    private CustomizeWorkerThread mCustomizeWorkerThread;
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initUIComponents();
        startWorkerThread();
    }
    private void initUIComponents()
    {
        mStartThreadButton = (Button) findViewById(R.id.startThread);
        mStartThreadButton.setOnClickListener(this);
        mResultTextView = (TextView) findViewById(R.id.textview);
    }
    private void startWorkerThread()
    {
        mCustomizeWorkerThread = new CustomizeWorkerThread(this);
        mCustomizeWorkerThread.start();
    }
    @Override
    public void onClick(View view)
    {
        int uiId = view.getId();
        switch (uiId) {
            case R.id.startThread:
                sendMessageToWorkerHandler();
                break;
        }
    }
    private void sendMessageToWorkerHandler()
    {
        Handler handler = mCustomizeWorkerThread.getHandler();
        if(handler != null){
            Message message = handler.obtainMessage(2);
            handler.sendMessage(message);
        }
    }
    public TextView getResultTextView()
    {
        return mResultTextView;
    }
    @Override
    protected void onDestroy()
    {
        super.onDestroy();
        mCustomizeWorkerThread.getHandler().getLooper().quit();
    }
}

 
以下為CustomizeWorkerThread的內容,
第10行為了取代匿名內部類別,另外建立了CustomizeWorkerHandler,該Handler負責處理從Looper傳送過來的Message
第18行的run方法相當重要,在run方法中連結了Looper,Thread,Handler三者。
第20行的Looper.prepare方法會建立Looper以及在該Looper中的MessageQueue,並連結到當前的Thread(CustomizeWorkerThread)
第21行建立CustomizeWorkerHandler物件並連結Looper
第22行Looper開始循序處理MessageQueue,為無限迴圈。當Message插入到MessageQueue中,Looper就會擷取該Message並發送到相關的Handler。
第25行回傳Handler讓外部可以藉由取得的Handler插入訊息
第31行即為CustomizeWorkerHandler,繼承 Handler
第41行必須複寫HandleMessage方法,當Looper傳送Message時,該方法即會被呼叫(callback)
第43行根據Message的what數值判斷行為
第45行就是網路存取的行為,HttpPageData.getPageData 會回傳google的網頁資料
第46行把取得的網頁資料設定到MainActivity的textview中

package com.foxx.threads;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
public class CustomizeWorkerThread extends Thread
{
    private static final String TAG = "WorkerThread";
    private CustomizeWorkerHandler mHandler;
    private MainActivity mMainActivity;
    public CustomizeWorkerThread(MainActivity activity) {
        mMainActivity = activity;
    }
    @Override
    public void run()
    {
        Looper.prepare();
        mHandler = new CustomizeWorkerHandler(mMainActivity);
        Looper.loop();
    }
    public CustomizeWorkerHandler getHandler()
    {
        return mHandler;
    }
}
class CustomizeWorkerHandler extends Handler
{
    private static final String TAG = "WorkerHandler";
    private MainActivity mMainActivity;
    public CustomizeWorkerHandler(MainActivity activity) {
        mMainActivity = activity;
    }
    public void handleMessage(Message message)
    {
        switch (message.what) {
            case 2:
                String result = HttpPageData.getPageData("https://www.google.com.tw/");
                setResultToMainActivity(result);
                break;
        }
    }
    private void setResultToMainActivity(final String result)
    {
        mMainActivity.runOnUiThread(new Runnable() {
            @Override
            public void run()
            {
                mMainActivity.getResultTextView().setText(result);
            }
        });
    }
}

 
接著簡單描述整個訊息傳送機制的互動過程,

建立訊息傳送機制

在 Activity 中會持有CustomWorkThread的類別成員(mCustomizeWorkerThread),
並在onCreate方法中建立實體,然後呼叫start方法,start方法會啟動CustomizeWorkerThread中的run方法,
該run方法會將worker thread,Looper, Handler 三者連結起來,到目前為止是整個傳遞訊息機制的建立,

發送訊息

在Activity中為了發送訊息到MessageQueue中,必須先建立訊息再藉由取得mCustomerWorkThread的Handler將訊息發送到MessageQueue中。

處理訊息

當訊息已經被發送到MessageQueue中,Looper便會自動擷取訊息,並將訊息發送到相對應的Handler,
相對應的意思為哪個Handler發送訊息,哪個Handler就會接收到訊息。
Handler藉由handleMessage方法來處理訊息。


以下為HttpPageData.java

package com.foxx.threads;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
public class HttpPageData
{
    /**
     * 取得網頁資料
     * @return : 回傳string型態的網頁資料
     */
    public static String getPageData(String httpUrl){
        java.net.CookieManager cm = new java.net.CookieManager();
        java.net.CookieHandler.setDefault(cm);
        URL u = null;
        InputStream in = null;
        InputStreamReader r = null;
        BufferedReader br = null;
        StringBuffer message = null;
        try {
           u = new URL(httpUrl);
           in = u.openStream();
           r = new InputStreamReader(in, "BIG5");//UTF-8
           br = new BufferedReader(r);
           String tempstr = null;
           message = new StringBuffer();
           while ((tempstr = br.readLine()) != null) {
               message.append(tempstr);
           }
        } catch (Exception e) {
           e.getStackTrace();
           System.out.println(e.getMessage());
        } finally {
           try {
              u = null;
              in.close();
              r.close();
              br.close();
           } catch (Exception e) {
           }
    }
        return message.toString();
    }
}

 

分類
Android Uncategorized

Set unban ip in fail2ban

How to set unban ip in fail2ban??

 
1. Edit /etc/fail2ban/jail.local and find ignoreip

[DEFAULT]
# "ignoreip" can be an IP address, a CIDR mask or a DNS host
ignoreip = 127.0.0.1/8 xxx.xxx.xxx.xxx

 
2. Input your unban ip as xxx.xxx.xxx.xxx
 
Note:
1. Remember use space to identify different ip
2. fail2ban commands
 

分類
Android Uncategorized

jenkins build error : error while writing Main: Main.class (Permission denied)

Description:

Build java project in jenkins and show error message

[javac] /path_of_class.java:1: error while writing Main: /path_of_class.class (Permission denied)
[javac] public class Main
[javac]        ^
[javac] 1 error

 

Root caused:

permission of directory is not enough
 

Solution:

1.
Open Terminal and move to parent of director which at java project
2.
sudo chmod 777 director_name
 

分類
Android Uncategorized

如何簡單的從TextView, EditView取得數值

通常輸入數值都會使用EditText等等的文字框當作對象, 如何才能很快速的從這些view取得數值呢??
使用 getText().toString() 加上各個數值類別(Integer, Double, Float, Long, Byte, Short)的ParseXXX() 最快 如下

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class GetValueFromTextView extends Activity
{
    private static final int PERCENT = 100;
    private static final int MONTH_COUNT = 12;
    private EditText mInput_lend;
    private EditText mInputRate;
    private EditText mInputNumber;
    private Button mSubmit;
    private TextView mAmount;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        initComponents();
    }
    private void initComponents()
    {
        mInput_lend = (EditText) findViewById(R.id.input_lend);
        mInputNumber = (EditText) findViewById(R.id.input_number);
        mInputRate = (EditText) findViewById(R.id.input_rate);
        mSubmit = (Button) findViewById(R.id.submit);
        mSubmit.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v)
            {
                mAmount.setText("" + countAmount());
            }
        });
        mAmount = (TextView) findViewById(R.id.amount);
    }
    private double countAmount()
    {
        int lend = Integer.parseInt(mInput_lend.getText().toString());
        double rateOfMonth = Double.parseDouble(mInputRate.getText().toString()) / MONTH_COUNT
                / PERCENT;
        int number = Integer.parseInt(mInputNumber.getText().toString());
        return lend * (Math.pow(rateOfMonth + 1, number));
    }
}

重點在 countAmount 方法中, 以下列方式取得string並轉換成數字

int lend = Integer.parseInt(mInput_lend.getText().toString());
double rateOfMonth = Double.parseDouble(mInputRate.getText().toString()) / MONTH_COUNT / PERCENT;
int number = Integer.parseInt(mInputNumber.getText().toString());

但要小心轉型溢位的問題
main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    <TextView
        android:id="@+id/main_tv_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/title"/>
    <TextView
        android:id="@+id/main_tv_lendHint"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/lend"/>
    <EditText
        android:id="@+id/input_lend"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:inputType="number"/>
    <TextView
        android:id="@+id/main_tv_rateHint"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/rate"/>
    <EditText
        android:id="@+id/input_rate"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:inputType="numberDecimal"/>
    <TextView
        android:id="@+id/main_tv_number"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/rate"/>
    <EditText
        android:id="@+id/input_number"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:inputType="number"/>
    <Button
        android:id="@+id/submit"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/btn"/>
    <TextView
        android:id="@+id/amount"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</LinearLayout>

以及 strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">Count Round-amount savings</string>
    <string name="title">Round-amount savings:</string>
    <string name="lend">capital(NT$):</string>
    <string name="rate">rate of year(%):</string>
    <string name="number">number of periods:</string>
    <string name="btn">count</string>
</resources>

 

分類
Android Uncategorized

取得 wifi scan ap result : ScanResult

在 android 手機中 -> 設定 -> Wi-Fi , 每隔一段時間會自動搜尋附近的wifi ap的訊息並顯示在列表上, 本篇介紹如何同步取得這些wifi ap的訊息
這些wifi ap的訊息是藉由ScanResult來顯示, ScanResult 類別相當簡單, 請參考官網
而每次搜尋wifi ap的動作都是以Broadcast的方式來達成, 所以我們只要建立一個專門來接收該動作的Broadcast Receiver 就能自動同步取得其搜尋結果(ScanResult)

package com.foxx.wifiapreceiver;
import java.util.List;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiManager;
import android.util.Log;
public class WifiApReceiver extends BroadcastReceiver
{
    private static final String TAG = "WifiApResult";
    private Activity mActivity;
    public WifiApReceiver(Activity activity) {
        mActivity = activity;
        mActivity.registerReceiver(this, new IntentFilter(
                WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
    }
    @Override
    public void onReceive(Context context, Intent intent)
    {
        getScanResults();
    }
    private void getScanResults()
    {
        List<ScanResult> scanResults = getWifiManager().getScanResults();
        Iterator<ScanResult> iter = scanResults.iterator();
        while (iter.hasNext()) {
            showAllFieldOfScanResult(iter.next());
        }
    }
    private WifiManager getWifiManager()
    {
        return (WifiManager) mActivity.getSystemService(Context.WIFI_SERVICE);
    }
    private void showAllFieldOfScanResult(ScanResult scanResult)
    {
        Log.d(TAG, "--------------------------------------");
        Log.d(TAG, "scanResult.SSID:" + scanResult.SSID);
        Log.d(TAG, "scanResult.BSSID:" + scanResult.BSSID);
        Log.d(TAG, "scanResult.capabilities:" + scanResult.capabilities);
        Log.d(TAG, "scanResult.frequency:" + scanResult.frequency);
        Log.d(TAG, "scanResult.level:" + scanResult.level);
        Log.d(TAG, "scanResult.BSSID:" + scanResult.describeContents());
    }
    public void unregisterReceiver()
    {
        try {
            mActivity.unregisterReceiver(this);
        } catch (Exception e) {
            Log.d(TAG, "execption in unregisterReceiver");
        }
    }
}

1. 在constructor註冊了receiver
2. OnReceiver 為 callback function , 只要有搜尋wifi ap的動作, OnReceiver就會被呼叫
 
在AndroidManifest.xml加入2個必要的permission

<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>

 
使用的方式相當簡單

package com.foxx.wifiapreceiver;
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity
{
    private WifiApReceiver mWifiReceiver;
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initWifiReceiver();
    }
    private void initWifiReceiver(){
        mWifiReceiver = new WifiApReceiver(this);
    }
    @Override
    protected void onStop()
    {
        mWifiReceiver.unregisterReceiver();
        super.onStop();
    }
}

只要注意在onStop要unregister receiver即可
 
 
 

分類
Android

Can't bind to local 8X00 for debugger

Description:

Debugger connected fail。
 

Solution:

開啟 eclipse 後 -> Window -> Preferences  -> Android -> DDMS
勾選 Use ADBHOST -> 127.0.0.1

分類
Android

eclipse android 實機装置顯示 ????????? unknow

Description:
接上實機後,Eclipse DDMS Devices 顯示 ??????????  ?? unknow
 
Solution:
開啟终端機輸入

sudo -s

輸入密碼取得  root 權限
移動到 SDK 中的 platfarm-tools 資料夾,其內要有adb檔案。
以下步驟可能要重複好幾次,直到顯示名稱OK
輸入

sudo ./adb kill-server

會開始Connection attempts
再輸入

sudo ./adb devices

如果装置有顯示名稱就OK了