想半天標題不知道怎下, 有點不是很貼切, 內容也寫的有點懶 :P 有可能會看不懂吧

最近開始想要一個禮拜想一個東西來實踐一下(不知道可以持續多久:P), 這禮拜想到的是這個: 從WebView內的javascript去叫起一個Activity, 然後把這Activity回傳的結果回傳給WebView內的javascript

具體的假想應用範例: import contact information, 從Javascript內叫contact picker, 並把所選的contact資訊匯入WebView內的form中

首先, 呼叫contact picker的範例如下:

public void launch()

{
    Intent intent = new Intent(Intent.ACTION_PICK);
    intent.setType(ContactsContract.Contacts.CONTENT_TYPE);
    startActivityForResult(intent, PICK_CONTACT);
}

基本上, 是要使用startActivityForResult, 這樣才能把所選定的contact給回傳給我們的Activity

但如何讓這lauch被javascript call到呢? 我們必須把這個method封裝到一個class內, 我用一個名叫ContactLauncher的class來做封裝, 並且將這個interface指定給WebView:

webView.addJavascriptInterface(new ContactLauncher(), “contactPicker”);

這樣一來, 我們在javascript內就有一個contactPicker可以供呼叫了, javascript的範例如下:

function launchPicker()
{
    if(contactPicker) {
         //register callback
          window.activitycallback = function(response) {
                  $(’#name’).val(response.name);
          };

          //call picker
         contactPicker.launch();
    } else { //no picker }
}

我們可以在javascript內透過"contactPicker.launch()“來叫起Contact picker, 這個就會直接呼叫ContactLauncher裡的lauch()

那在這之前的程式碼是幹啥用的呢? 由於launch()並不是一個blocking call, 並不會等到結果回傳後才結束, 而我們又要startActivityForResult回傳回來的資料, 因此我們需要一個callback來接收回傳的資料

那怎讓javascript可以接收回傳回來後的資料呢, 這邊我利用一個類似javascript injection的方式來做(原理是利用WebView可以接收"javascript:"這種形態的url)

以下是onActivityResult的實作 (這邊偷懶只取一個Display name):

protected void onActivityResult(int requestCode, int resultCode, Intent data) { if(requestCode == PICK_CONTACT) { Cursor c = managedQuery(data.getData(), null, null, null, null); c.moveToNext(); String name = c.getString(c.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME));  String json = "{name:'"+name+"'}"; webView.loadUrl("javascript:window.activitycallback("+json+");"); } }

 

因為在WebView內的那個javascript page我已經先安插了一個activitycallback, 所以就利用loadUrl來呼叫它, 這樣就大功告成了!

這只是一個簡單的範例, 還可以做的更generic一點, 比如說把傳入的資料轉化成json這段, 這招應該還可以做一些應用才對

Nfc

想不出啥好idea來利用NFC, 所以呢, 身體力行勝於一切, 寫隻小範例體驗一下比較真切, 所幸Android NFC API並不難, 從研究API到寫出這個範例, 比我畫上面那張圖花的時間還更短….

接收的範例已經有了NFC Demo, 而且我比較想體驗一下P2P的狀況, 所以就寫了隻push的範例

這範例的功能如:

Idea

功能很簡單: 在Browser瀏覽網頁時按下Menu->Share page->NFC Push demo, 然後拿另一支NFC裝置來讀取分享的頁面, 因此這一頁面需要能透過NFC push去發送一個含有欲分享的URL的Message

首先要讓這隻程式支援NFC, 在AndroidManifest.xml有三個必要的要素:

  1. SDK level >= 10: <uses-sdk android:minSdkVersion=“10” />
  2. NFC feature : <uses-feature android:required=“true” android:name=“android.hardware.nfc”></uses-feature>
  3. Permission for NFC: <uses-permission android:name=“android.permission.NFC”></uses-permission>

然後我們必須要一個Activity來支援URL的發送, 這個URL要包裝成NdefMessage

NdefRecord rec = new NdefRecord(NdefRecord.TNF_ABSOLUTE_URI, NdefRecord.RTD_URI, new byte[0],share.getBytes());

new NdefMessage(new NdefRecord[]{rec})

要支援push, 只需要在onResume時使用enableForegroundNdefPush就可以了, onPause記得把它disable (沒disable會怎樣? 我碰到狀況是, 沒disable, 可能連之後讀取似乎都有問題) , 文件裡面是說要在main thread裡呼叫, 但試驗結果是, 也不能放在onCreate

Android API 網站上有一篇介紹NFC的, 還算蠻簡單的

完整的範例程式在此

用了iOS 5大約一個多星期了, 感覺上是差不多可以出了, 雖然大大小小bug還是有, 不過, 之前正式版的iOS 4我也常遇到bug呀~

比較方便的改進就是新的notification吧, 以前的notification難用到我直接關掉, 這次這個Android notification的copycat就好多了…..

跟Android一樣也是下拉就會出現, 不過跟Android不同的是, 會是以應用程式為主分群, 另外可以加兩個widget(天氣, 股票), 但Android如果在Full screen狀況下是無法知道有notification的, iOS這個是連在Full screen 的狀況下也可以下拉使用(就由上往下的手勢操作), 試過在玩Angry birds時也可以, 這樣就比在Android上方便一點

_3

設定上就稍嫌複雜太多

_4

在Lock screen上也蠻方便的, 直接解鎖就到該AP去了

_1
_2

 

說實在的, 這一點都不算創新, 反而比較像完全的抄襲, 但又稍微有點小小的改良後, 還算方便啦…

自從看了Google I/O上Reto Meier用兩台Xoom做簡報, 就一直很想這樣做, 光靠手機和tablet做簡報, 而不是靠笨重的電腦, 上次去大陸出差, 用iPad+Keynote當場做投影片當場簡報, 這樣做還蠻爽的, 只是好像離我理想中(通常都過大)還差很遠, Reto Meier有說要放出Source, 但我等好久了….Source咧…. orz

今天跟人又討論起這東西, 回家路上, 順便把我想要的function design隨便塗鴉出來:

Photo_6_09_1_24_04_
我想要的是, 手機當remote control還可以看小抄, tablet負責投影還有錄音錄影(用後面的攝影機錄觀眾, 或是用前置攝影機錄自己), 還有錄投影片的timeline (以後可以合成教學影片)….最好是可以拿手機當雷射筆(不知道光靠內建的Sensor夠不夠當指向裝置)

哇哈哈…這聽起來好像好難…我好像太挑剔了… XD

最近為了想實現device 2 device的auto discovery/communication ,特別去研究了bonjour/mdns,今天跑去GTUG時,試著想利用mdns從我的mbp找我的手機時一直不成功,起初還以為我程式有問題,抓了封包,卻找不到mdns的封包,後來才發現到,原來我手機連上的wireless ap跟mbp連上的是不同一台,雖然同屬同一家咖啡廳,但卻是不同的subnet,當然就收不到multicast的封包

有了這樣一個經驗後,當下就開始思考(哈,台上講的我老早就沒認真聽了),利用multicast做這樣的應用到底實不實用,雖然說不管是mdns也好,還是upnp用的ssdp,都還蠻適合這類應用的,而且它們都是以udp multicast來實作,但對mobile device而言,特色是不會固定attach在同一個network,ip也隨時在變,利用multicast的方式大概只有在同一個wifi網路之下比較適用,要做真正 decentralized device 2 device discovery好像有點難度

因此後來我又轉往另一個想法,geographical peer to peer,剛剛想了幾個簡單的想法,先寫下來

Why peer 2 peer?

其實只是很單純的想讓在同一區域的mobile devices可以不用透過某一個central server來交換資料,或是通訊,甚至達到類似c2dm的功效,所以想是個可以處理peer 2 peer communication的service,支援的application只需要跟它註冊服務資訊,收到的request就以broadcast intent的方式交給相關服務處理。

大部分的P2P network像是BitTorrent, Napster, Gnutella, eDonkey, Tor都是為了分享而存在, 也有像是Skype是為了通訊, 由於我最初的想法是想達到zero configuration的通訊跟分享, 所以第一方面就往這方向的機制去想, 當然也不是為了做一個像BitTorrent這樣規模的東西

Why geographical?

最早的想法是local share, 也就是在同一個區域, 比如說同一個房間, 同一間會議室裡的mobile device之間的相互分享溝通, 所以最早想到的是Bonjour類型(基於mDNS), 不過如前述, 問題就存在於這些裝置未必在同一個sub net, 甚至是有些未必是用wifi, 也有可能是3G

想到的作法是: 借用BUMP的作法來建立一個虛擬的區域網路, 這"區域"是實際地理位置上的區域, 而非一般的LAN, 現在的mobile device, 大多都有定位系統, 取得地理位置資訊並不難, BUMP的作法是將地理相關的資訊例如IP, GPS座標等等資訊傳送到Server, 藉以判定是哪兩台做互碰的動作, 我想同一個原理應該可以用來協助建立一個地理上的local network, BUMP是用於兩台不同device之間, 但同一個原理也應該適用來建立一個這樣的network

How?

剛在回家路上把想法畫了一個簡單的架構圖

Cameraroll-1307545188
分為幾個步驟:
  1. Check in: Device用目前的位置資訊如IP, GPS座標等等向Registry註冊
  2. Seeding: Registry server利用device傳回來的位置資訊找出實際地理範圍內最近註冊的幾個裝置(時間也是必要元素), 並回傳給device
  3. Discover: Device根據回傳的seed名單, 一個個訪問所有的Seed, 並取得他們所支援的services, 以及他們的鄰居, 並持續這動作直到network到一定大小或是沒任何的新鄰居
  4. Connect and communicate: 建立服務連線並取用服務

這是一個大體上的架構, 應該還有很多細節, 比如說像是notification when join network等等

應用?

想到的應用像是file/data sharing, gaming network, data sync between different devices, chat room等等…

 

這只是一個簡單的想法而已, 還沒去想得很完整, 也還沒想到是不是有啥缺陷