2013年6月28日 星期五

[Android] Retrofit + Signpost : 替Retrofit加上OAuth支援

看到Square發表的這個Retrofit - http://square.github.io/retrofit/ 蠻有趣的, 它的目的似乎是試圖的想要去簡化開發REST client, 開發者不用寫太多的邏輯, 只要寫一個Interface跟利用annotation就可以完成一個簡單的REST client:

public interface GitHubService {
  @GET("/users/{user}/repos")
  List<Repo> listRepos(@Path("user") String user);
}

因為開發者只需要寫interface和annotation, 實質上並不用寫任何的code, 真正實作的部份他用了Proxy class的技巧包裝起來了, 這作法讓我想起來很久之前我在之前的工作幫公司寫的一個legacy系統的wrapper, 那時有很多機器產生的interface, 如果人工一個個實作很浪費時間, Proxy class可以解決掉這一部分的問題, 同樣的在retrofit似乎也是想用這技巧節省實作

但可惜的是, 現在的retrofit並還沒加入OAuth的支援, 因此送出去的API部分並沒被oauth簽章過,不過所幸要解決這一部分也不難, 寫一個Client class搭配Signpost還是可以做到, 這邊範例繼承了OkClient(使用OkHttp) :



因為OkHttp也是一種HttpURLConnection, 因此Signpost搭配DefaultOAuthProvider和DefaultOAuthConsumer即可, 另外初始化RestAdapter時加上這個新的Client即可:

RestAdapter restAdapter = new RestAdapter.Builder() .setClient(new SignedOkClient(mConsumer))

2013年6月26日 星期三

[Android] 自定義View屬性

前一篇寫了一個自訂義的layout - SimpleCellLayout, 前一個版本的問題就是, 必須是寫程式把child view加進這個layout之中, 而且針對像是欄與行的數目也必須在程式裡設定, 並無法寫到layout xml中, 所以這次的目邊就是要讓這個layout可以像下面這樣用layout xml來擺佈:


在這範例之中, 用到幾個像是col, row, gapsize, cellX這些在原生Android並不存在的屬性, 為了這些屬性, 就需要定義一個attrs.xml在res/values目錄內, attrs.xml 裡面要定義的就是這些樣式描述屬性, 這邊定義了: 給SimpleCellLayout本身用的col(欄數), row(行數), gapsize(間距大小), 以及給他的Child views用的cellX(格子的橫軸位置), cellY(格子的縱軸位置), colspan(格子寬), rowspan(格子高), 除了gapsize我們需要的跟實際螢幕上的大小有關, 所以格式定義為dimension外(就是可以用3dp, 1px這類的值), 其他都是整數就可

這些屬性, 到時候就是要放在xml標籤內的屬性

要用到這些屬性, 需要先在tag裡面定義一個新的name space, 如同在前面範例寫的:

xmlns:celllayout="http://schemas.android.com/apk/res-auto"
文件內的範例大多是apk/後面接著package name, 不過Android Studio卻是建議使用"res-auto", 定義了這個name space後, 便可以在後面的tag內使用像是"celllayout:col"這樣的屬性了

那在layout內又要怎處理這些屬性? ViewGroup有兩個建構子所需要帶的參數含有AttributeSet, 基本上只要從這兩個建構子處理就好

這範例內的initFromAttributes就是用來從AttributeSet擷取這些屬性, 前面attrs.xml有定義stylable, 所以基本上有一堆相對應的Resource ID可以使用,這邊只處理了col, row, 和gapsize, 因為只有這三個屬性直接跟這layout相關, 至於這layout的child views該怎處理呢? 它就要靠LayoutParams了, 我在SimpleCellLayout內定義了一個CellLayoutParams, 基本上這類別也有一個建構子是用來處理AttributeSet的


這邊比較重要的就是要overwrite掉generateLayoutParams, 因為ViewGroup原有的generateLayoutParams實作的是回傳ViewGroup.LayoutParams, 他並不認得CellLayoutParams, 但SimpleCellLayout靠的是CellLayoutParams來儲存layout所需的資訊, 原本用程式來加入view的範例部份, 我是手動產生一個CellLayoutParams來給child view, 但如果是放在layout xml, 並無法指定要用哪個LayoutParams類別, 這時候就要靠generateLayoutParams了 有趣的是, 雖然是我自訂的layout, 但在我做完這些後, Android studio的UI編輯器, 卻知道怎去依據我的layout把元件畫到正確的位子上面:

2013年6月25日 星期二

[Android] 一個簡單的自製 layout - SimpleCellLayout

寫Android寫了這麼久, 才想到自己沒寫過custom layout, 剛剛花了點時間(主要時間還是花在跟Android studio和gradle搏鬥)寫了一個簡單的CellLayout (還很陽春) :

https://github.com/julianshen/SimpleCellLayout

寫custom layout還蠻簡單的, 在onMeasure決定自己和child views的大小, 在onLayout時把每個child views放到適當的位置, 目前還沒加入attibrtues的支援, 所以暫時還只能寫code自己把view加進去, 另外也還沒加檢查是不是會有重疊的views, 之後再來寫

這個layout跟GridView不同, 可以不用每個格子都是同一大小, 以下範例是把畫面劃成4x4的格子, 左上角的那張圖大小是2x2, 下方則是 4x2



2013年6月21日 星期五

[Android] 圓形大頭貼 - 使用Picasso的Transformation

現在不管是Google+也好, 或是Facebook (Home), 似乎都很喜歡用圓形的大頭貼像這樣 (左上角圖形,

但在server端存的大頭照其實都是都是方形的, 所以必須抓下來後再轉畫成圓的, 最近從網路抓圖的部分, 我還蠻喜歡用Picasso

沒啥別的原因, 就是它簡單, 雖然說, 它似乎還是有一些小小問題, 不過它可以用這樣短短一行解決圖檔下載並顯示到ImageView的一連串動作:

Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);

不過, 簡單的代價可能在其他的地方來說彈性就不高了, 不過, 做這樣一個小玩意兒的彈性倒是還有, 在Picasso中, 可以實作Transformation把下載下來的圖檔再作一次後處理, 在它的網頁有一個CropSquareTransformation的範例, 圓形的大頭貼可以視為這一個的延伸:

這邊利用了BitmapShader重畫了一張圓形的大頭貼, 出來的結果就會像是這樣:


2013年6月20日 星期四

[Android] 一閃一閃亮晶晶的BlinkLayout

Androids Do Daydream裡有提到Romain Guy要他提(大概假的吧)在layout裡面放"<blink>"可以做到view閃爍的效果而不用寫到一行code

查了一下AOSP的原始碼也的確有這東西, 它是一個躲在LayoutInflater的一個叫BlinkLayout的東西, 這樣一來就可以配合TextClock (API Level 17)來做一個閃爍的時鐘了


不過, 這樣, 是整個TextClock在閃, 而不是像一般數字鐘一樣是只有":"閃, 如果要做到只有":"在閃, 那只好把"時"跟"分"給拆開, 像這樣:

2013年6月16日 星期日

[筆記][Android Studio]Git push

本想說有直接整合了Git, GitHub是件不錯的事, 沒想到要把新project push到remote git就栽了....

Android Studio/Intellij 似乎沒介面設定remote (搜尋了半天沒發現這種答案, 啃了半天的使用手冊也沒發現), 現在如果要把既有的project給匯出到遠端的git (如bitbucket), 就得利用command line (以bitbucket 為例):

  1. 在bitbucket上create一個新的project
  2. 在Android studio選"VCS"->"Import into version control"->"Create Git repository", 這樣就可以建立一個local的repository
  3. "VCS"->"Git"->"Add to VCS"
  4. "VCS"->"Git"->"Commit File"
  5. 到command line下切換到project目錄下"git remote add origin ssh://git@bitbucket.org/xxx/xxx.git"
  6. 回到Android studio, "VCS"->"Git"->"Push"
要注意的是, 如果你已經有一個remote repository,"VCS"->"Import into version control"->"Share project on GitHub"會失敗


2013年6月15日 星期六

[筆記] Android Studio, Gradle & Native libraries

最近試用Android studio開發, 可能有些習慣被以往Eclipse慣壞了, 剛剛發現放在libs/底下的東西不像以前會被自動建置到apk內, 有點小訝異, 對jar file來說, 可能還好不算太難, 在build.gradle的dependencies內補上一筆就夠了, 但對native library (jni)那些.so檔, 就沒辦法

用這樣解決了 Google了一下, 並且在Stack overflow上找到些解法來試, 可能因為Android studio跟Gradle Android plugin還一直在變化中, 在現在這版一直沒成功, 後來小改一下成底下這樣就成功了:


原本找到的解法是pkgTask.jniDir new File('build/native-libs') , 這樣會得到
> Directory 'build/native-libs' specified for property 'jniDir' does not exist.
把"new File"改成"file"就沒問題了,不過現在一切應該都還在開發中, 未來可能會有原生的native lib 支援也不一定, 未來可能這方法也不管用了吧